首页 > 编程知识 正文

jvm回收机制的三大算法,jvm垃圾回收如何实现标记

时间:2023-05-04 18:29:10 阅读:33200 作者:3986

上一篇文章介绍了JVM的内存模型。 本文介绍了JVM垃圾回收的工作原理。

如何定义垃圾

有两种方法。 一个是引用计数(但无法解决循环引用问题)。 另一个是可达性分析。

对象判断为可以回收时:

与对象弱引用相关的对象垃圾收集方法Mark-Sweep标记-清除算法 (老年代),这种方法优点就是减少停顿时间,但是缺点是会造成内存碎片。,其中一个引用指向NULL或对另一个对象的本地引用。

Copying复制算法, 这种方法不涉及到对象的删除,只是把可用的对象从一个地方拷贝到另一个地方,因此适合大量对象回收的场景,比如nqdwx代的回收。

Mark-Compact标记-整理算法,这种方法可以解决内存碎片问题,但是会增加停顿时间。

按世代分类的常规收集

最后这种方法是前面几种合并,也就是目前JVM主要采用的方法之一,思想是将JVM划分为不同的区域。 每个地区使用不同的垃圾回收方法。

上面可以看到堆分成三个区域:

3358 www.Sina.com/http://www.Sina.com/http://www.Sina.com /

nqdwx代-复制算法

该算法的核心是将可用内存按容量划分为大小相同的两个块,每次只使用一个块,当该块的内存耗尽后,将仍然活着的对象复制到另一块,将使用完的内存空间一次性使用

由此,每次只回收1张存储器,不考虑存储器碎片化等复杂状况,就能够实现简单且有效的运用.

现代商用虚拟机的nqdwx代都采用复制算法,但98%的nqdwx代对象生存周期极短,因此不是完全按1:1的比例划分nqdwx代空间。 将nqdwx层代划分为一个大kdxmg区域和两个小Survivor区域(如果每次仅使用kdxmg和一个Survivor时发生MinorGC,则将仍然存在于kdxmg和Survivor中的对象划分为另一个survivivor区域) 如果Survivor空间不足(不足以保存生存对象),则为

nqdwx代(Young Generation):用于存放新创建的对象,采用复制回收方法,如果在s0和s1之间复制一定次数后,转移到年老代中。这里的垃圾回收叫做minor GC;

该算法分为“标记”和“清除”两个阶段,首先标记所有要回收的对象(可达性分析),标记完成后,批量清除所有标记的对象。

该算法存在以下两个问题:

1 .效率问题:标识和通关流程效率不高;

2 .清除空间问题:标记会导致大量不连续的内存碎片。 如果空间碎片过多,则在运行时需要分配大对象时可能找不到足够的连续内存,必须提前触发另一个垃圾回收。

年老代(Old Generation):这些对象垃圾回收的频率较低,采用的标记整理方法,这里的垃圾回收叫做 major GC。

标签清理算法会引起内存碎片化的问题,但由于复制算法需要额外的内存保证空间,针对旧时代的特点,有标签清理算法。标签清理算法的标签标注在之后的步骤中,不是直接清理可再利用的对象,而是将所有生存的对象移动到一端,清理端部边界以外的内存。

永久-方法区回收利用

方法区进行垃圾回收一般“性价比”较低。 方法区主要回收2个内容:处置常数和浪费类别。 回收废弃常数与回收其他年代的对象相似,但必须判断一个

类是否无用则条件相当苛刻: 该类所有的实例都已经被回收, Java堆中不存在该类的任何实例;该类对应的Class对象没有在任何地方被引用(也就是在任何地方都无法通过反射访问该类的方法);加载该类的ClassLoader已经被回收.

但即使满足以上条件也未必一定会回收, Hotspot VM还提供了-Xnoclassgc参数控制(关闭CLASS的垃圾回收功能). 因此在大量使用动态代理、CGLib等字节码框架的应用中一定要关闭该选项, 开启VM的类卸载功能, 以保证方法区不会溢出.

附:(面试被问到过)

Minor GC ,Full GC 触发条件

 

Major GC 清理年老区(Tenured space).Full GC 清理整个内存堆 – 既包括年轻代也包括年老代.

Minor GC触发条件:当kdxmg区满时,触发Minor GC。

Full GC触发条件:

(1)调用System.gc时,系统建议执行Full GC,但是不必然执行

(2)老年代空间不足

(3)方法去空间不足

(4)通过Minor GC后进入老年代的平均大小大于老年代的可用内存

(5)由kdxmg区、From Space区向To Space区复制时,对象大小大于To Space可用内存,则把该对象转存到老年代,且老年代的可用内存小于该对象大小

 

JVM小工具

 

在${JAVA_HOME}/靓丽的棉花糖/目录下Sun/Oracle给我们提供了一些处理应用程序性能问题、定位故障的工具, 包含

靓丽的棉花糖描述功能jps打印Hotspot VM进程VMID、JVM参数、main()函数参数、主类名/Jar路径jstat查看Hotspot VM 运行时信息类加载、内存、GC[可分代查看]、JIT编译jinfo查看和修改虚拟机各项配置-flag name=valuejmapheapdump: 生成VM堆转储快照、查询finalize执行队列、Java堆和永久代详细信息jmap -dump:live,format=b,file=heap.靓丽的棉花糖 [VMID]jstack查看VM当前时刻的线程快照: 当前VM内每一条线程正在执行的方法堆栈集合Thread.getAllStackTraces()提供了类似的功能javap查看经javac之后产生的JVM字节码代码自动解析.class文件, 避免了去理解class文件格式以及手动解析class文件内容jcmd一个多功能工具, 可以用来导出堆, 查看Java进程、导出线程信息、 执行GC、查看性能相关数据等几乎集合了jps、jstat、jinfo、jmap、jstack所有功能jconsole基于JMX的可视化监视、管理工具可以查看内存、线程、类、CPU信息, 以及对JMX MBean进行管理jvisualvmJDK中最强大运行监视和故障处理工具可以监控内存泄露、跟踪垃圾回收、执行时内存分析、CPU分析、线程分析…VM常用参数整理 参数描述-Xms最小堆大小-Xmx最大堆大小-Xmnnqdwx代大小-XX:PermSize永久代大小-XX:MaxPermSize永久代最大大小-XX:+PrintGC输出GC日志-verbose:gc--XX:+PrintGCDetails输出GC的详细日志-XX:+PrintGCTimeStamps输出GC时间戳(以基准时间的形式)-XX:+PrintHeapAtGC在进行GC的前后打印出堆的信息-Xloggc:/path/gc.log日志文件的输出路径-XX:+PrintGCApplicationStoppedTime打印由GC产生的停顿时间

 

 

总结

在众多的垃圾回收器中,没有最好的,只有最适合应用的回收器,根据应用软件的特性以及硬件平台的特点,选择不同的垃圾回收器,才能有效的提高系统性能。

Minor GC 和 Full GC 有什么区别?

nqdwx代 GC (Minor GC) :发生在nqdwx代的垃圾收集动作。Minor GC 非常频繁,回收速度比较快。

老年代 GC (Major GC/Full GC):发生在老年代的 GC, Major GC 一般比 Minor GC 慢 10 倍以上。

内存分配规则

对象优先在 kdxmg 分配

大多数情况下,对象在nqdwx代 kdxmg 区中分配。当 kdxmg 区没有足够空间进行分配时,虚拟机将发起 Minor GC。

大对象直接进入老年代

长期存活的对象将进入老年代

虚拟机给每个对象定义了一个对象年龄(Age)计数器。如果对象在 kdxmg 出生在 Survivor 区中每熬过一次 Minor GC,年龄加 1 岁,当年龄到一定程度(默认15岁),就会晋升到老年代中。

动态对象年龄判定

在 Survivor 空间中相同年龄所有对象大小的总和大于 Survivor 空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代。

空间分配担保

在发生 Minor GC 之前,虚拟机会先检查老年代最大可用的连续空间是否大于nqdwx代所有对象总空间,如果这个条件成立,那么 Minor GC 可以确保是安全的。如果不成立,则虚拟机会查看 HandlePromotionFailure 设置值是否允许担保失败。如果允许,那么会继续检查老年代最大可能连续空间是否大于历次晋升到老年代对象的平均大小,如果大于,将尝试着进行一次 Minor GC,尽管这个 Minor GC 是有风险的;如果小于,或 HandlePromotionFailure 设置不允许冒险,那这次也要改为进行一次 Full GC。

优秀的编程习惯

(1)避免在循环体中创建对象,即使该对象占用内存空间不大。
(2)尽量及时使对象符合垃圾回收标准。
(3)不要采用过深的继承层次。
(4)访问本地变量优于访问类中的变量。


 

 

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。