大家都知道我们java中有个虚拟机叫做jvm,但是真正了解人却不多。今天我就把这些零散的知识点回顾下。
垃圾回收机制,是sun公司定义的一个规则,但是真正垃圾回收的机制的算法却不是sun公司的,是各个厂商自己拥有的。既然是垃圾回收机制,那么怎么判断是垃圾或者不是垃圾。这个就需要我们的搜索算法来完成我们的想法。
垃圾回收机制的完成主要分成两个部分来进行,
第一步:通过搜索算法确定我们所谓的垃圾。
第二步:通过回收算法进行回收。
搜索算法:
一,引用计数器算法(已经淘汰)
这个算法在每个对象创建出来的时候,就设置了一个计数器,当这个对象被调用的时候,计数器就增加1,当引用失效的时候,计数器就-1,当计数器为0 的时候,JVM就认为对象不再使用,是一个"垃圾"。引用器的实现简单,效率高,但不能解决循环引用的问题。这样就导致计数器的增加和减少带来很多额外的开销。所以,在jdk1.1之后就不在使用。
二,根搜索算法(目前在用)
这个算法主要是通过一些 " GC Roots"对象作为起点。从这些节点往下搜索,搜索的路径成为引用链,当这个对象没有被GC Roots引用的时候就意味着这个对象不可用,就会被当做垃圾。
回收算法:
关于generation的知识点
虚拟机中的共划分为三个代:年轻代(Young Generation)、老年代(Old Generation)和持久代(Permanent Generation)。
年轻代:所有新生成的对象首先都是放在年轻代的。年轻代的目标就是尽可能快速的收集掉那些生命周期短的对象。年轻代分三个区。一个Eden区,两个Survivor区(一般而言)。大部分对象在Eden区中生成。当Eden区满时,还存活的对象将被复制到Survivor区(两个中的一个),当这个Survivor区满时,此区的存活对象将被复制到另外一个Survivor区,当这个Survivor去也满了的时候,从第一个Survivor区复制过来的并且此时还存活的对象,将被复制“年老区(Tenured)”。
老年代:在年轻代中经历了N次垃圾回收后仍然存活的对象,就会被放到年老代中。因此,可以认为年老代中存放的都是一些生命周期较长的对象。
持久代:存放的是Java类的类信息,与垃圾收集要收集的Java对象关系不大。年轻代和年老代的划分是对垃圾收集影响比较大的。
关于CMS
什么是CMS?
CMS是一款并发、使用标记-清除算法的GC
CMS是针对老年代进行回收的GC。
CMS有什么作用?
CMS以获取最小停顿时间为目的。
在一些对响应时间有很高要求的应用或网站中,用户程序不能有长时间的停顿,CMS 可以用于此场景。
CMS执行的流程:
初始标记:标记GC roots能直接关联到的对象,速度快,执行时间短,会stop the world。
并发标记:GC roots追踪的过程,不会stop the world,执行时间相对较长。
重新标记:修正并发标记期间产生的变动,初始标记<重新标记执行时间<并发标记或并发清除,会stop the world。
并发清除:垃圾回收,不会stop the world,执行时间相对较长。
JVM的调优
JVM调优目标
一,何时需要做jvm调优?什么情况下需要对jvm做调优?
1. heap 内存(老年代)持续上涨达到设置的最大内存值;
2. Full GC 次数频繁;
3. GC 停顿时间过长(超过1秒);
4. 应用出现OutOfMemory 等内存异常;
5. 应用中有使用本地缓存且占用大量内存空间;
6. 系统吞吐量与响应性能不高或下降。
二,调优原则
JVM调优原则:
1、多数的Java应用不需要在服务器上进行JVM优化;
2、多数导致GC问题的Java应用,都不是因为我们参数设置错误,而是代码问题;
3、在应用上线之前,先考虑将机器的JVM参数设置到最优(最适合);
4、减少创建对象的数量;
5、减少使用全局变量和大对象;
6、JVM优化是到最后不得已才采用的手段;
7、在实际使用中,分析GC情况优化代码比优化JVM参数更好;
三,调优目标
JVM调优目标 :
1. GC低停顿;
2. GC低频率;
3. 低内存占用;
4. 高吞吐量;
JVM调优量化目标(示例):
1. Heap 内存使用率 <= 70%;
2. Old generation内存使用率<= 70%;
3. avgpause <= 1秒;
4. Full gc 次数0 或 avg pause interval >= 24小时 ;
注意:不同应用,其JVM调优量化目标是不一样的。