博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JVM 垃圾回收
阅读量:5910 次
发布时间:2019-06-19

本文共 3503 字,大约阅读时间需要 11 分钟。

hot3.png

什么对象可以被 JVM 回收?

        Java 通过可达性分析算法,来判断对象是否存活。这个算法是通过一系列称为 “GC ROOTS” 的对象为起始点,从这些起始点向下检索,检索所走过的路径称为引用链(Reference Chain)。当一个对象到 “GC ROOTS” 没有任何引用链,则该对象可以被回收。(传统的引用计数法,并不能作为对象是否可回收的依据,因为它无法解决对象之间相互引用的问题)

        Java 语言中可以作为 “GC ROOTS” 的对象有:

  1. 虚拟机栈中引用的对象;

  2. 方法中类静态属性引用的对象;

  3. 方法区常量引用的对象;

  4. 本地方法栈中 JNI(即 Native 方法) 引用的对象

方法区的垃圾回收:

      方法区(HotSpot虚拟机的永久代)的垃圾主要回收两部分的内容:废弃常量和无用的类。废弃常量的回收和堆中的对象十分类似。只要没有任何对象引用常量池中的常量,该常量就可以回收;判断一个常量是否是废弃常量比较简单,但如何判断一个类是“无用的类”,需要满足以下3个条件。

        1. 该类的所有实例都已经被回收,也就是Java 堆中不存在该类的任何实例;

        2. 加载该类的 ClassLoader 已经被回收;

        3. 该类对应的 java.lang.Class 对象没有任何地方被引用,无法在任何地方通过反射访问该类的方法垃圾回收算法

 

标记-清除算法(Mark-Sweep)

    首先标记出所有需要回收的对象,然后在标记完成后,统一收集。缺点:1. 效率比较低;2. 会产生大量的内存碎片,到最后导致在分配大对象时,找不到足够的内存空间.会再次触发垃圾收集。

复制算法(Copying)

    将内存划分为大小相等的两块,每次只使用其中的一块,当一块用完了。就把上面存活的对象复制到另外一块。然后,将前面一块整体清除。缺点:将内存缩小为原来的一半,成本有点高。现代商业虚拟机都使用这种算法收集新生代,因为新生代的对象都是朝生夕死的。不需要 1:1来划分内存空间。一般是分为一块较大的 Eden 区和两块较小的 Survivor 区。HotSpot 虚拟机默认 Eden 和 Survivor 的大小比例为 8:1。

标记-整理算法(Mark-Compact)

    复制算法在对象存活率较高的老年代,就不适合,需要更多的复制操作,这时就不能选用这种算法。根据老年代的算法,使用标记-整理算法。即让所有存活的对象都向一侧移动,然后直接清除边界以外的内存。

分代收集算法(Generational Collection)

    当前商业虚拟机的垃圾收集都采用 “分代收集” 算法,这种算法根据对象存活周期划分为几块。一般把 Java 堆分为新生代和老年代。新生代每次垃圾回收都有大量的对象死去,使用复制算法。老年代对象存活率高使用 “标记-整理” 算法。

垃圾收集器(下图为HotSpot 虚拟机的垃圾收集器)

    

        

没有最合适的虚拟机,只能针对不同应用选择最合适的收集器,上图为新生代和老年代的各类收集器,有连线代表可以一起使用。

Serial 收集器

    单线程收集器,它在垃圾收集时,必须暂停所有的工作线程(Stop the World)。该收集器由于没有线程交互的开销,可以获得最高的单线程收集效率,适合运行在 Client 模式下的虚拟机。

ParNew 收集器

    ParNew 收集器是 Serial 收集器的多线程版本。它可以与 CMS 收集器配合工作。

Parallel Scavenge 收集器

    该收集器是一个新生代收集器,它也是使用复制算法的收集器。Parallel Scavenge 收集器的目的是达到一个可控制的吞吐量(Throughtput).所谓吞吐量是 CPU 用于运行用户代码时间与 CPU 总消耗时间的比值。高吞吐量可以高效的利用 CPU 时间,尽快完成程序的运算任务,适合在后台运算而不需要太多交互的任务。

Servial Old 收集器

    该收集器是 Servial 收集器的老年代版本,它同样是一个单线程收集器,使用“标记-整理”算法,该收集器主要给 Client 模式下的虚拟机使用。

Parallel Old 收集器

    该收集器是 Parallel Scavenge 收集器的老年代版本, 使用多线程和“标记-整理”算法。

CMS 收集器

    CMS(Concurrent Mark Sweep) 收集器是一种以获取最短回收停顿时间为目标的收集器。 B/S 系统和很多应用很重视服务的响应速度,希望系统停顿时间最短,以给用户最佳的体验。CMS 收集器适合这样的场景。 CMS收集器工作的整个流程分为以下4个步骤,整个过程中,最为耗时的并发标记和并发清除时,收集器线程可以与用户线程一起工作。

  1. 初始标记(CMS initial mark):仅仅只是标记一下GC Roots能直接关联到的对象,速度很快,需要“Stop The World”。

  2. 并发标记(CMS concurrent mark):进行GC Roots Tracing的过程,在整个过程中耗时最长。

  3. 重新标记(CMS remark):为了修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间一般会比初始标记阶段稍长一些,但远比并发标记的时间短。此阶段也需要“Stop The World”。

  4. 并发清除(CMS concurrent sweep)  

G1 收集器

    G1(Garbage-First) 是最新一代收集器,它具有以下特点:

  1. 并行与并发: G1 能够充分利用多 CPU,多核环境的优势,缩短 Stop-The-World  停顿的时间,部分其他收集器需要停顿用户线程执行 GC 动作, G1 收集器可以通过并发让 Java 线程继续运行;

  2. 分代收集: 它可以独立管理整个堆,但它可以使用不同的方式处理新建的对象和已经存活了一段时间的对象、经过多次 GC 的对象,可以获得更好的收集效果;

  3. 空间整合: G1 从整体上看是基于 “标记-整理” 算法实现的收集器。从局部看是基于“复制”算法,这意味着 G1 在运行期间不会产生内存碎片,利于程序长期稳定的运行,不会触发 GC 去为大对象分配内存。

  4. 可预测的停顿: 可以指定一个停顿时间;

     

对象分配规则

  1. 对象优先分配在Eden区,如果Eden区没有足够的空间时,虚拟机执行一次Minor GC。

  2. 大对象直接进入老年代(大对象是指需要大量连续内存空间的对象)。这样做的目的是避免在Eden区和两个Survivor区之间发生大量的内存拷贝。通过参数-XX:PretenureSizeThreshold=3145728控制。

  3. 长期存活的对象进入老年代。虚拟机为每个对象定义了一个年龄计数器,对象每熬过了1次Minor GC对象的年龄加1,达到阀值对象进入老年区。通过参数-XX:MaxTenuringThreshold=15(默认)控制。

  4. 动态判断对象的年龄。如果Survivor区中相同年龄的所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象可以直接进入老年代,无需等到MaxTenuringThreshold要求的年龄数。

  5. 空间分配担保。每次进行Minor GC时,JVM会计算Survivor区移至老年区对象的平均大小,如果这个值大于老年区的剩余值大小则进行一次Full GC,如果小于检查HandlePromotionFailure设置,如果true则只进行Monitor GC,如果false则进行Full GC。 (-XX:-HandlePromotionFailure)

Young Generation(新生代): 分为:Eden区和Survivor区,Survivor区有分为大小相等的From Space和To Space。

Old Generation(老年代):  当 OLD 区空间不够时, JVM 会在 OLD 区进行 major collection。

Minor GC:    新生代GC,指发生在新生代的垃圾收集动作,因为java对象大多都具备朝生夕死的特性,所以Minor GC非常频繁,一般回收速度也比较快。

Full GC/Major GC:   发生老年代的GC,对整个堆进行GC。出现Major GC,经常会伴随至少一次Minor GC(非绝对)。MajorGC的速度一般比minor GC慢10倍以上。

转载于:https://my.oschina.net/freedemon/blog/1827366

你可能感兴趣的文章
小程序上传图片到七牛云(支持多张上传,预览,删除)
查看>>
spring boot 整合mybatis 无法输出sql的问题
查看>>
为什么要用IPython/Jupyter?
查看>>
Angular js 常用指令ng-if、ng-class、ng-option、ng-value、ng-click是如何使用的?
查看>>
创建一种深思熟虑的文化
查看>>
数据可视化之 Sankey 桑基图的实现
查看>>
项目实战-Api的解决方案
查看>>
前端面试题总结
查看>>
(三)从jvm层面了解线程的启动和停止
查看>>
SOA和微服务之间的区别
查看>>
Cable:360实现的新虚拟网络架构
查看>>
IBM提出8位深度网络训练法,提速4倍同时保持高精度
查看>>
ArchSummit北京2015大会九大看点
查看>>
苹果发布Core ML 2
查看>>
“智能云”战略新品震撼发布,开发者如何快速上手?
查看>>
华为吴晟:分布式监控系统的设计与实现
查看>>
[deviceone开发]-do_Webview的基本示例
查看>>
亚马逊Alexa借助神经网络生成播音员声音
查看>>
比特大陆新一轮裁员50%,回应称系人员调整
查看>>
[nginx文档翻译系列] 控制nginx
查看>>