Java虚拟机-1-JVM内存分布

一、JVM内存分布

1、JVM内存模型

JVM内存模型主要包括:类加载器,运行时数据区域,本地方法库、本地方法接口,执行引擎和垃圾回收器

运行时数据区域主要包括:【线程独享】:虚拟机栈、本地方法栈、程序计数器,【线程共享】:堆、方法区

2、类加载器

类加载器用于懒加载字节码文件(.class文件),为程序执行做准备

如果程序执行某个行为所需要的类还没有被加载到内存当中,则会经过三个步骤来完成类的初始化

  1. 加载:加载字节码文件到内存当中
  2. 连接
    1. 验证:字节码文件是否有正确的结构
    2. 准备:分配类的一些信息到内存区域
    3. 解析:将类的二进制数据中的符号引用替换为直接引用
  3. 初始化:创建对象的实例

JVM的类加载器分为

  1. BootstrapClassLoader(启动类加载器):加载JRE运行时类,位于$JAVA_HOME/jre/lib/rt.jar
  2. ExtClassLoader(扩展类加载器):加载JRE扩展类,位于$JAVA_HOME/jre/lib/ext目录下
  3. AppClassLoader(应用程序类加载器):加载Java程序的类
  4. User ClassLoader(自定义加载器)

双亲委派模型:当类加载器加载类时,先尝试由父类加载器加载,如果父类加载器无法完成,则再由子类加载器来完成

沙箱安全机制:由于双亲委派模型的存在,所以我们无法自己创建类似于JDK自带的类(全类名完全相同)

双亲委派模型的破坏:Apache Tomcat是一个Web容器,用于部署Web应用,它就破坏了双亲委派模型,把类的加载直接交给Web应用类加载器(WebappClassLoader)来完成,如果Web应用类加载器(WebappClassLoader)无法完成,再由通用类加载器(CommonClassLoader)来完成。这样做的目的主要是为了保证每一个Web应用都是相互独立的,不会因为依赖着相同的类(全类名),而版本的不同造成混乱

Tomcat的类加载器分为

  1. BootstrapClassLoader:加载基本的JVM环境的类,位于$JAVA_HOME/lib目录下
  2. SystemClassLoader:加载Tomcat的启动类,位于$CATALINA_HOME/bin目录下
  3. CommonClassLoader:加载Tomcat的通用类,位于$CATALINA_HOME/lib目录下
  4. WebappClassLoader:加载Web应用的类,位于WEB-INF/lib目录和WEB-INF/classes目录下。仅对当前Web应用可访问

3、虚拟机栈

Java Stack,主要用于存放基本数据类型和实例对象的引用等

4、本地方法栈

Native Method Stack,和Java Stack类似,为运行native方法而准备的

5、程序计数器

Program Counter Register,用于保存要执行的下一条指令

6、堆

Heap,主要用于存放对象的实例、数组和字符串常量池等

垃圾回收的主要区域,分为新生代和老年代,默认比例为1:2,可以通过修改JVM参数-XX:NewRatio=2来调整

新生代又分为伊甸园区、from区和to区,默认比例为8:1:1。可以通过修改JVM参数-XX:SurvivorRatio=8来调整

发生在新生代的GC称之为Minor GC,发生在老年代的GC称之为Major GC,发生在整个堆的GC称之为Full GC(包括对永久代的回收)

7、方法区

Method Area,主要用于存放类的信息(静态变量、构造方法、方法声明等)和运行时常量池(常量等)等

JVM规范将方法区描述为堆的一个逻辑部分,但是它却有一个别名叫做Non-Heap(非堆),目的是和堆区分开来

在HotSpot虚拟机上,方法区又被称之为永久代(Permanent Generation),这仅仅是因为HotSpot用永久代来实现方法区而已,在其他虚拟机上(BEA JRockit、IBM J9等)来说,是不存在永久代的概念的。但是这种实现做法容易遇到内存溢出的问题(OOM),可以通过修改JVM参数 [JDK7]-XX:PermSize=???-XX:MaxPermSize=???[JDK8]-XX:MetaspaceSize=???-XX:MaxMetaspaceSize=???来调整

猜你喜欢

转载自blog.csdn.net/adsl624153/article/details/103865446
今日推荐