架构师成长之路

JVM垃圾回收

2018-04-12  本文已影响1人  一一道长一一

一、JVM内存区域划分和作用

JVM内存区域划分和作用

设置JVM各区域的大小:
-Xmx :堆的最大值
-Xms :堆的最小值
-Xmn :堆新生代的大小
-Xss :每个线程的栈大小,决定了函数调用的最大深度
示例:-Xmx512m -Xms512m -Xmn64m -Xss256k 设置堆的最大值和最小值都为512M(可以避免扩容带来的性能损耗),新生代大小为64M,每个栈的大小为256k(过大会造成浪费)

方法区存放内容:

  1. 类的全限定名(类的全路径名)。
  2. 类的直接超类的权全限定名(如果这个类是Object,则它没有超类)。
  3. 类的类型(类或接口)。
  4. 类的访问修饰符,public,abstract,final等。
  5. 类的直接接口全限定名的有序列表。
  6. 常量池(字段,方法信息,静态变量,类型引用(class))等 ,jdk1.7之前字符串常量存在常量池中,之后被移到了堆中
  • 延伸理解字符串的intern方法(面试前必看):字符串的intern方法的理解,常使用String.intern()来优化大量字符串,intern用来返回常量池中的某字符串,如果常量池中已经存在该字符串,则直接返回常量池中该对象的引用。否则,在常量池中加入该对象,然后返回引用。
  • JVM中的四种引用强度排序:强引用>弱引用>软引用>虚引用
  • JVM在回收对象之前会调用一次对象的finalize()方法,但是仅调用一次,不建议在java中使用finalize方法

二、分代垃圾收集

  1. 新生代,用来存放新出生的对象,新生代又分为 Eden区、ServivorFrom、ServivorTo三个区,由于创建对象频繁,新生代会频繁触发MinorGC(基于复制算法的垃圾收集器)进行垃圾回收。
  • Eden区:Java新对象的出生地(如果新创建的对象占用内存很大,则直接分配到老年代)。当Eden区内存
    不够的时候就会触发MinorGC,对新生代区进行一次垃圾回收。
  • ServivorTo:保留了一次MinorGC过程中的幸存者。
  • ServivorFrom:上一次GC的幸存者,作为这一次GC的被扫描者
  1. 老年代,主要存放应用程序中生命周期长的内存对象。
  • 老年代的对象比较稳定,所以MajorGC/FullGC(基于标记-整理算法的垃圾收集器)不会频繁执行。在进行MajorGC/FullGC前一般都先进行了一次MinorGC,使得有新生代的对象晋身入老年代,导致空间不够用时才触发 。
  • 对象每熬过一次MionorGC,对象的年龄+1,当对象的年龄达到一定年龄(默认是15)的时候就会进入老年代
  • 大对象直接进入老年代,对象的大小边界可通过-XX:PretenureSizeThreshold参数进行配置
新生代进入老年代的过程
  1. 永久代,JDK7之前分配在方法区中,主要存放Class和Meta(元数据)的信息,Class在被加载的时候被放入永久区域
  • 在Java8中,永久代已经被移除,被一个称为“元数据区”(元空间)的区域所取代
  • 元空间与永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用本地内存,这样可以加载多少类的元数据就不再由MaxPermSize控制, 而由系统的实际可用空间来控制

三、JVM垃圾收集算法

  1. 引用计数法

因为循环引用的问题,jvm并没有采用这个算法

  1. 可达性分析算法

GCroot对象包括:虚拟机栈中引用的对象、方法区中静态属性和常量引用的对象、本地方法栈中JNI(Native方法)引用的对象

  1. 标记-清除算法
  1. 复制算法
  1. 标记-整理算法

四、JVM常用垃圾收集器

HotSpot中的7种垃圾收集器
  1. Serial和Serial Old收集器

Serial是最古老的垃圾收集器,Serial Old是Serial的老年代版本,二者据用同样的垃圾优缺点

Serial和Serial Old收集器一起使用的运行示意图
  1. ParNew收集器——Serial的多线程版本


    ParNew收集器的运行示意图
  1. Parallel Scavenge和Paralle Old收集器——“吞吐量”优先的收集器
  • Paralle Old是Parallel Scavenge的老年代版本,二者具有相同的优缺点,都关注吞吐量
  • 吞吐量=运行用户代码时间 / (运行用户代码时间+垃圾收集时间)
Paralle Scavenge和Paralle Old配合使用的运行示意图
  1. CMS收集器——以获得最短停顿时间为目标的收集器

CMS收集器是基于“标记-清除”算法的收集器,收集过程分为四步:

  • 初始标记,只标记一下GCRoot能直接关联到的对象,速度很快,耗时短,不能与用户线程并行
  • 并发标记,进行GC Roots Tracing(GCRoot可达性分析)的过程,耗时最长,可与用户进程并行
  • 重新标记,修正并发标记期间因用户程序继续运行而导致标记变动的那一部分的标记记录,耗时比初始标记长,但远比并发标记的时间短,不能与用户线程并行
  • 并发清除,耗时也很长,但可与用户线程并行
CMS运行示意图
  1. G1收集器——面向服务端应用的垃圾收集器

G1收集器是jdk1.7之后才有的垃圾收集器,是收集器技术最前沿的成果, G1的设计思想包括:

  • 化整为零,将整个java堆划分为多个大小相等的独立区域(Region),新生代和老年代不再物理隔离,只是逻辑隔离
  • 跟踪个各个Region的回收价值(回收后所获得的空间大小和所需时间),在后台维护一个优先列表,每次根据允许的收集时间优先收集回收价值最大的Region
  • 使用Remembered Set来避免全堆扫描,G1中每个Region都有一个对应的Remembered Set,记录了该Region中的对象对其他Region中对象的引用信息(希望我理解的没问题),当进行内存回收时,在GC根节点枚举范围加入RememberedSet即可保证不对全堆扫描也不会有遗漏

G1垃圾收集过程分为四步:

  • 初始标记,只是标记一下GCRoot能直接关联到的对象,速度快,耗时短,不能与用户线程并行
  • 并发标记,进行GC Roots Tracing(GCRoot可达性分析)的过程,耗时最长,可与用户进程并行
  • 最终标记,修正在并发期间因用户程序继续运行而导致标记产生变化的那一部分标记记录,不能跟用户线程并行
  • 筛选回收,对各个Region的回收价值和成本进行排序,根据用户期望的GC停顿时间制定回收计划。
G1收集器运行示意图

五、JVM垃圾收集器常用参数

参数的使用方法:

示例:-XX:+PrintGC -XX:+PrintGCDetails 打开打印GC的信息和详细信息

垃圾回收相关参数配置
上一篇下一篇

猜你喜欢

热点阅读