博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JVM垃圾回收相关知识笔记
阅读量:4209 次
发布时间:2019-05-26

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

上次说到jvm的内存模型,也就是说对象存在的区域。因为代码是循环往复的执行。也就是创建对象是肯定得。因此堆和方法区(元空间)肯定要兼容不断产生的新对象。而且还要保证效率。但是考虑到我们的虚拟机栈出栈之后其中引用的堆中的对象其实已经没什么用了,所以说清理不用的对象是垃圾回收的关键。也是java项目不被运行产生的对象憋死的关键。那么如何去清理这些对象就是一个关键。

至于这个关键的动作,其实是需要分两步,第一步就是找到,第二步就是回收。对应的就是对象存活的判断算法和垃圾回收算法。其中对象存活判断算法主要有引用计数法和可达性分析算法。其中引用记数法的问题是死循环问题,相互引用最后导致谁到没办法回收最后就会占用堆空间。有可能产生oom现象。可达性分析算法主要就是通过GC roots来查看对象是否可以访问。如果访问不了,那么垃圾回收器就会将这些孤立的数据节点进行回收。

在判断对象是否可以回收之后,就要进行垃圾回收作业。当然我们在垃圾回收的时候需要考虑很多事情,比如内存的实际情况,内存碎片,效率等因素。

如果不考虑到上述因素,那么垃圾回收算法。最简单的就是将判为可回收的对象进行标记,然后进行清理,也就是标记清除算法。然而这种算法容易导致内存碎片。既然有内存碎片,那么我们就可以清除之后整理这些碎片,也就是标记整理算法。这是两种解决的思路。而年轻代作为对象生成区,对象产生的频繁,而且绝大多数的对象都是通过虚拟机栈的栈帧引用的,所以会很快释放。所以这块的对象特点是存活时间短,新建的多。所以jvm设计人员做这块创建了复制算法。复制算法针对from和to区。通过复制算法将存活的对象转移到so或者s1区域,甚至在某些空间不足的条件下复制到老年代中。

综合上述,我们知道垃圾回收算法主要有标记清除,标记整理,复制。

既然有了算法,那么就要有具体的实现。而对这些算法的实现就是垃圾回收器。当然对于不同的堆内存区域有不同的垃圾回收器。这块我们这里简单的进行一些探索。

年轻代的垃圾回收器

Serial、parNew、Parallel Scavenge

老年代垃圾回收器

Serial old、paralled old、CMS

特殊收集器

G1(不再区分年轻、老年代)

从字面理解很容易说明上述收集器的特定。serial表示单线程,parNew是一种支持多线程的垃圾回收器。但是其任然和serial一样,会有卡顿(stop the world),会让所有的java线程停止。我们可以在使用该收集器的时候指定垃圾回收的线程数--XX:ParallelGCThreads.

Parallel Scavenge采用的是复制算法,支持多线程。该收集器注重吞吐率,是一种吞吐率优先的收集器。

同样的对老年代的垃圾收集器来说,Serial old也是单线程,也会有stw的问题。采用的是标记整理算法。大概得流程如下,这里的安全点就是说用户线程不能再操作堆的一种锁机制。

paralled old表示多线程老年代垃圾回收。算法依然是标记整理。java8中默认的老年代垃圾回收就是paralled old收集器。在与年轻代的配合中,一般是Parallel Scavenge。

CMS垃圾收集器是一种和用户线程并行的垃圾收集器。这种方式的好处就是我们的垃圾收集无时无刻的在进行,有效的降低了安全点对用户线程的影响。极大的提升了虚拟机的响应时间。避免了stw,当然也存在一定的问题。那就是垃圾回收线程刚刚收集了一片空间,然后新的垃圾又在刚清理的空间上产生,这种垃圾叫做浮动垃圾,当然要做到和用户现场的并发执行,所以就不能整理堆上的对象,只能采用标记清除的方法,故而会产生内存碎片。由于上述的种种问题,可能 导致待分配的空间不足,从而引发fullGc。

G1收集器是目前最强的存在,其模糊了年轻代和老年代的界限,通过分区的方式进行空间分配,也就是说每个分区可能是年轻代也有可能是老年代。但是G1收集器的使用必须在java8及以上版本。

一些经典的调优配置

以下内容抄自知乎作者:Andy.Zhou

原文链接:https://www.cnblogs.com/andy-zhou/p/5327288.html

吞吐量优先

java -Xmx3800m -Xms3800m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:ParallelGCThreads=20-XX:+UseParallelGC:选择垃圾收集器为并行收集器。此配置仅对年轻代有效。即上述配置下,年轻代使用并发收集,而年老代仍旧使用串行收集。-XX:ParallelGCThreads=20:配置并行收集器的线程数,即:同时多少个线程一起进行垃圾回收。此值最好配置与处理器数目相等。

java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:ParallelGCThreads=20 -XX:+UseParallelOldGC

-XX:+UseParallelOldGC:配置年老代垃圾收集方式为并行收集。JDK6.0支持对年老代并行收集。

java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC  -XX:MaxGCPauseMillis=100

-XX:MaxGCPauseMillis=100:设置每次年轻代垃圾回收的最长时间,如果无法满足此时间,JVM会自动调整年轻代大小,以满足此值。

java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC  

-XX:MaxGCPauseMillis=100 -XX:+UseAdaptiveSizePolicy -XX:+UseAdaptiveSizePolicy:设置此选项后,并行收集器会自动选择年轻代区大小和相应的Survivor区比例,以达到目标系统规定的最低相应时间或者收集频率等,此值建议使用并行收集器时,一直打开

响应时间优先

java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:ParallelGCThreads=20 

-XX:+UseConcMarkSweepGC -XX:+UseParNewGC 

-XX:+UseConcMarkSweepGC:设置年老代为并发收集。测试中配置这个以后,-XX:NewRatio=4的配置失效了,原因不明。所以,此时年轻代大小最好用-Xmn设置。-XX:+UseParNewGC: 设置年轻代为并行收集。可与CMS收集同时使用。JDK5.0以上,JVM会根据系统配置自行设置,所以无需再设置此值。

java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseConcMarkSweepGC -XX:CMSFullGCsBeforeCompaction=5 -XX:+UseCMSCompactAtFullCollection 

-XX:CMSFullGCsBeforeCompaction:由于并发收集器不对内存空间进行压缩、整理,所以运行一段时间以后会产生“碎片”,使得运行效率降低。此值设置运行多少次GC以后对内存空间进行压缩、整理。-XX:+UseCMSCompactAtFullCollection:打开对年老代的压缩。可能会影响性能,但是可以消除碎片

你可能感兴趣的文章
关于USB Gadget开发
查看>>
tofel词汇
查看>>
jellybean的suspend策略变动
查看>>
Android linux的休眠和唤醒
查看>>
高通msm8x60 boot(lk)的usb处理解析流程
查看>>
MSM8260 EHCI-MSM72k主控制器的状态机迁移分析
查看>>
MSM8x60 OTG之设备控制器流程分析
查看>>
MSM8X60 USB控制器流程分析
查看>>
sd卡驱动分析之card
查看>>
sd卡驱动分析之core
查看>>
sd卡驱动分析之host
查看>>
sd卡驱动分析之相关硬件操作和总结
查看>>
好的播文
查看>>
linux dd命令解析
查看>>
linux find命令详解
查看>>
S3C2440上touchscreen触摸屏驱动
查看>>
ARM-Linux驱动-触摸屏驱动分析
查看>>
GPIO的上拉电阻的作用
查看>>
kernel power off流程分析
查看>>
Qualcomm pmic充电流程分析(msm8660)
查看>>