JVM原理(二)类加载机制与GC算法

一. 类的加载机制

  1. 过程
    1. 将.class的二进制数据读入内存,放入方法区中
    2. 在堆中创建一个java.lang.Class对象,封装类在方法区中的数据结构,并提供访问方法区数据结构的接口
  2. 类的生命周期
    1. 类的加载过程
      1. 加载:查找并加载类的二进制数据,在堆中创建java.lang.Class类对象
      2. 连接
        1. 验证:文件格式,元数据,字节码,符号引用验证
        2. 准备:为类的静态变量分配内存,并将其初始化为默认值
        3. 解析:把类中的符号引用转换为直接引用
      3. 初始化:为类的静态变量赋正确的初始值
    2. 使用:new出对象,程序中使用
    3. 卸载:执行垃圾回收
    4. 图示:JVM原理(二)类加载机制与GC算法_第1张图片
  3. 类加载器:
    1. 分类:
      1. 启动类加载器:加载JDK\jre\lib下或者被-Xbootclasspath指定的路径下的类库
      2. 扩展类加载器:加载JDK\jre\lib\ext下或者被java.ext.dirs指定的类库(javax.*开头)
      3. 应用程序类加载器:加载用户类路径所指定的类(ClassPath)
    2. 父子关系JVM原理(二)类加载机制与GC算法_第2张图片
  4. 类加载机制
    1. 全盘负责:当一个类加载器加载某个类,则这个类引用的其他class也有该类加载器负责载入
    2. 父类委托:先让父类加载器加载,如果不能加载,在从自己的类路径加载
    3. 缓存机制:所有加载过得类都会被缓存,然后当需要使用某个class时,先看缓存区中是否存在(所以改完class需要重启JVM)

二. jvm内存结构

  1. 组成:
    1. Java堆:存放对象实例,所有线程共享
      1. 组成
        1. 年轻代(括号中是内存比例)
          1. Eden(8)
          2. From Survivor(1)
          3. To Survivor(1)
        2. 老年代
      2. 控制参数
        1. -Xms设置堆的最小空间大小。
        2. -Xmx设置堆的最大空间大小。
        3. -XX:NewSize设置新生代最小空间大小。
        4. -XX:MaxNewSize设置新生代最大空间大小。
        5. -XX:PermSize设置永久代最小空间大小。
        6. -XX:MaxPermSize设置永久代最大空间大小。
        7. -Xss设置每个线程的堆栈大小。
    2. 方法区:存放虚拟机已经加载的类,常量,静态变量,即时编译器编译的代码,所有线程共享
    3. 程序计数器:当前线程执行的字节码的行号指示器,线程私有
    4. JVM栈:声明周期和线程相同,每个方法调用到执行,对应栈帧在JVM栈中入栈出栈
    5. 本地方法栈:与JVM栈相似,虚拟机用到的Native方法的入栈出栈
  2. 内存结构图示:JVM原理(二)类加载机制与GC算法_第3张图片
  3. 对象分配规则
    1. 对象优先分配Eden区:如果Eden区没有足够空间,执行一次Minor GC
    2. 大对象(需要大量连续内存空间的对象)直接进入老年代:为了避免在Eden和Survivor发生大量数据拷贝(年轻代使用复制算法收集内存)
    3. 长期存活的对象进入老年代:长期存活的判定是,有一个年龄计数器,对象经过一次MinorGc,进入Surviror,之后每经过一次MinorGC,则年龄加1,到达一定值,进入老年区
    4. 动态判断对象的年龄:如果Survivor区中相同年龄的所有对象,大小总和大于Survivor的一半,则大于等于该年龄的对象可以直接进入老年代
    5. 空间分配担保:每次进行Minor GC时,JVM会计算Survivor区移至老年区的对象的平均大小,如果这个值大于老年区的剩余值大小则进行一次Full GC,如果小于检查HandlePromotionFailure设置,如果true则只进行Monitor GC,如果false则进行Full GC。

三. GC算法

  1. 对象存活判断
    1. 两种方式:
      1. 引用计数:有一个引用的时候这个对象的引用计数属性加1,引用释放之后,计数减1,为0表示可回收
      2. 可达性分析:从GC Roots开始向下搜索,搜索所走过的路径称为引用链。当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的,不可达对象。
        1. GC Roots包括:
          1. 虚拟机栈中引用的对象。
          2. 方法区中类静态属性实体引用的对象。
          3. 方法区中常量引用的对象。
          4. 本地方法栈中JNI引用的对象。
  2. GC算法
    1. 基础算法
      1. 标记 -清除算法:算法分为“标记”和“清除”两个阶段:首先标记出所有需要回收的对象,在标记完成后统一回收掉所有被标记的对象。
      2. 复制算法:将可用内存分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。
      3. 标记-压缩算法,标记过程仍然与“标记-清除”算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存
    2. 分代收集算法(垃圾回收器使用):
      1. 年轻代:复制算法
      2. 老年代:标记-清除和标记-压缩
  3. 垃圾回收器及组合策略表格

 

垃圾回收器

年轻代

老年代

参数控制

目标

Serial收集器

串行,复制

串行,标记-压缩

-XX:+UseSerialGC  串行收集器

 

ParNew收集器

并行,复制

串行,标记-压缩

-XX:+UseParNewGC  ParNew收集器

-XX:ParallelGCThreads 限制线程数量

 

Parallel收集器

自适应,复制

串行,标记-压缩

-XX:+UseParallelGC  使用Parallel收集器+ 老年代串行

最合适的停顿时间

最大的吞吐量

Parallel Old 收集器

自适应,复制

并行,标记-压缩

 -XX:+UseParallelOldGC 使用Parallel收集器+ 老年代并行

最合适的停顿时间

最大的吞吐量

CMS收集器

ParNew收集器

并行,标记-清除

-XX:+UseConcMarkSweepGC  使用CMS收集器

-XX:+ UseCMSCompactAtFullCollection Full GC后,进行一次碎片整理;整理过程是独占的,会引起停顿时间变长

-XX:+CMSFullGCsBeforeCompaction  设置进行几次Full GC后,进行一次碎片整理

-XX:ParallelCMSThreads  设定CMS的线程数量(一般情况约等于可用CPU数量)

获取最短回收停顿时间

优点:并发收集,低停顿

缺点:产生大量碎片,并发阶段会降低吞吐量

G1收集器

并行,标记-压缩

并行,标记-压缩

-XX:+UnlockExperimentalVMOptions -XX:+UseG1GC   开启

-XX:MaxGCPauseMillis =50   暂停时间目标

-XX:GCPauseIntervalMillis =200   暂停间隔目标

-XX:+G1YoungGenSize=512m  年轻代大小

-XX:SurvivorRatio=6    幸存区比例

 

 

常用组合

新生代GC策略

年老代GC策略

说明

组合1

Serial

Serial Old

Serial和Serial Old都是单线程进行GC,特点就是GC时暂停所有应用线程。

组合2

Serial

CMS+Serial Old

CMS(Concurrent Mark Sweep)是并发GC,实现GC线程和应用线程并发工作,不需要暂停所有应用线程。另外,当CMS进行GC失败时,会自动使用Serial Old策略进行GC。

组合3

ParNew

CMS

使用-XX:+UseParNewGC选项来开启。ParNew是Serial的并行版本,可以指定GC线程数,默认GC线程数为CPU的数量。可以使用-XX:ParallelGCThreads选项指定GC的线程数。

如果指定了选项-XX:+UseConcMarkSweepGC选项,则新生代默认使用ParNew GC策略。

组合4

ParNew

Serial Old

使用-XX:+UseParNewGC选项来开启。新生代使用ParNew GC策略,年老代默认使用Serial Old GC策略。

组合5

Parallel Scavenge

Serial Old

Parallel Scavenge策略主要是关注一个可控的吞吐量:应用程序运行时间 / (应用程序运行时间 + GC时间),可见这会使得CPU的利用率尽可能的高,适用于后台持久运行的应用程序,而不适用于交互较多的应用程序。

组合6

Parallel Scavenge

Parallel Old

Parallel Old是Serial Old的并行版本

组合7

G1GC

G1GC

-XX:+UnlockExperimentalVMOptions -XX:+UseG1GC        #开启

-XX:MaxGCPauseMillis =50                  #暂停时间目标

-XX:GCPauseIntervalMillis =200          #暂停间隔目标

-XX:+G1YoungGenSize=512m            #年轻代大小

-XX:SurvivorRatio=6                            #幸存区比例

你可能感兴趣的:(JVM原理)