1 jvm结构图

jvm知识点总结-LMLPHP

2 类的装载器

jvm知识点总结-LMLPHP
​  将类的字节码文件加载到jvm中,会把这些内容转化为方法区运行的数据结构。jvm会创建对应的Class对象,保存到堆中。

装载器有如下几种:虚拟机自带装载器:启动类加载器(BootStrap)C++、扩展类加载器(Extension)Java、应用程序类加载器(AppClassLoader)Java,也叫系统类加载器,加载当前应用的classpath的所有类
用户自定义加载器:Java.lang.ClassLoader的子类

双亲委派机制:如果一个类收到加载的请求,他首先会让它的父类尝试去完成,当他的父类无法完成时,它才会尝试加载这个类。

沙箱:比如启动类加载器它加载了java.lang.String,如果本地也是创建相同的包且有String类,它会以启动的时候首先加载的那个类为准。

3 执行引擎

​功能:解释命令,提交给操作系统执行。

4 本地方法栈、本地方法接口、本地方法库

​  native修饰的方法是本地方法,由于java代码无能为力,可能需要调用操作系统或C++等代码。这些方法会注册到本地方法栈,这些本地方法通过调用本地方法接口调用非java代码,执行引擎会加载本地方法库。

5 PC寄存器

​  用于指向当前线程所执行的字节码的行号显示器

6 方法区

​  存储类的结构信息,有静态变量(静态域),运行时常量池、字段和方法数据、构造函数和普通方法的字节码内容。在jdk7中这里是永久代,jdk8采用的是元空间实现。

7 栈

​  在线程创建时创建,线程结束栈内存也结束,所有不存在垃圾回收。栈中存储8种基本数据变量、对象的引用变量、实例方法。栈中存储的方法就是栈帧,存储三种数据,本地变量:输入输出参数以及方法内的变量,栈的操作:记录入栈和出栈、栈帧数据:方法。
​  栈中存储直接对象的地址,堆中存储对象以及类元数据的地址即Class的地址,方法区存储类元数据。

8 堆

jvm知识点总结-LMLPHP
​  在jdk7中堆在逻辑上分为新生区,养老区,永久存储区,而在物理上堆只有新生区和养老区,永久存储区为方法区,在jdk8中永久区被原空间取代,二者区别时永久存储区使用堆内存,而元空间的大小和物理内存有关。
​  在伊甸区如果对象满了,会触发 Minor GC ,会把存活的对象移动到幸存0区(from),对象的年龄加一。第二次伊甸区对象满了,会把幸存0区和伊甸区存活的对象复制到幸存1区并且年龄加一,幸存0区有from区变为to区,幸存1区由to变为from区,清理伊甸区和to区,这样一直进行下去,如果哪些对象年龄达到15,就会进入养老区,这个值也可以自己设置,在jdk8种在0-15之间。如果养老区满了,会触发full gc。

9 GC算法

​  分代收集算法,新生区和养老区采用的算法是不一样的,由于新生区发生gc比较频繁,而养老区次数比较少,在jdk7中永久存储区基本不清理,在jdk8中元空间不使用堆内存故不需要清理。

9.1 引用计数法

​在每次引用时,会加一,置为null会减一,但是这个算法有如下缺点,要使用计数器,会有内存消耗,无法处理循环引用。

9.2 复制算法

​触发 Minor GC ,会把存活的对象移动到幸存0区(from),对象的年龄加一。第二次伊甸区对象满了,会把幸存0区和伊甸区存活的对象复制到幸存1区并且年龄加一,幸存0区有from区变为to区,幸存1区由to变为from区,清理伊甸区和to区,这样一直进行下去,如果哪些对象年龄达到15,就会进入养老区。

缺点:①:消耗内存
②:如果生存率高的化,也是比较浪费的。
这个算法在新生区使用,因为新生区存活率低。

9.3 标记清除

​①:从根集合开始扫描,对存活的对象进行标记
​②:扫描整个内存空间,清理未被标记的对象。

缺点:需要暂停整个应用,会产生内存碎片
老年代一般是由标记清除或者是标记清除与标记整理的混合实现

9.4 标记压缩

​①:从根集合开始扫描,对存活的对象进行标记
​②:将标记的对象移动到一边,不需要清理

缺点:虽然不需要回收对象,但是不仅要标记所有存活对象,还要整理所有存活对象的引用地址。

还有一个算法是标记清除压缩算法,这个算法结合3,4,和标记清除是类似的,只不过多次gc后才进行压缩。
老年代一般是由标记清除或者是标记清除与标记整理的混合实现

06-08 12:03