垃圾回收机制

垃圾回收机制算法分析-LMLPHP

内存泄露

下面是几条容易上手的建议,来帮助你防止内存泄漏的发生。
特别注意一些像HashMap、ArrayList的集合对象,它们经常会引发内存泄漏。当它们被声明为static时,它们的生命周期就会和应用程序一样长。
特别注意事件监听和回调函数。当一个监听器在使用的时候被注册,但不再使用之后却未被反注册。
“如果一个类自己管理内存,那开发人员就得小心内存泄漏问题了。” 通常一些成员变量引用其他对象,初始化的时候需要置空。

垃圾回收机制算法

引用计数法

垃圾回收机制算法分析-LMLPHP
优点:
引用计数收集器可以很快的执行,交织在程序运行中。对程序需要不被长时间打断的实时环境比较有利。
缺点:
无法检测出循环引用。如父对象有一个对子对象的引用,子对象反过来引用父对象。这样,他们的引用计数永远不可能为0.而且每次加减非常浪费内存。

复制算法

垃圾回收机制算法分析-LMLPHP

标记清除算法

垃圾回收机制算法分析-LMLPHP
标记-清除(Mark-Sweep)算法顾名思义,主要就是两个动作,一个是标记,另一个就是清除。
标记就是根据特定的算法(如:引用计数算法,可达性分析算法等)标出内存中哪些对象可以回收,哪些对象还要继续用。
标记指示回收,那就直接收掉;标记指示对象还能用,那就原地不动留下。
垃圾回收机制算法分析-LMLPHP
缺点
标记与清除没有连续性效率低;
清除之后内存会产生大量碎片;
所以碎片这个问题还得处理,怎么处理,看标记-整理算法。

标记-压缩算法

标记压缩法在标记清除基础之上做了优化,把存活的对象压缩到内存一端,而后进行垃圾清理。(java中老年代使用的就是标记压缩法)

分代收集算法

根据内存中对象的存活周期不同,将内存划分为几块,java的虚拟机中一般把内存划分为新生代和年老代,当新创建对象时一般在新生代中分配内存空间,当新生代垃圾收集器回收几次之后仍然存活的对象会被移动到年老代内存中,当大对象在新生代中无法找到足够的连续内存时也直接在年老代中创建。
对于新生代和老年代来说,新生代回收频率很高,但是每次回收耗时很短,而老年代回收频率较低,但是耗时会相对较长,所以应该尽量减少老年代的GC.

为什么老年代使用标记压缩、新生代使用复制算法。

垃圾回收时的停顿现象–这就是为什么会降低程序效率

垃圾回收的任务是识别和回收垃圾对象进行内存清理,为了让垃圾回收器可以更高效的执行,大部分情况下,会要求系统进如一个停顿的状态。停顿的目的是为了终止所有的应用线程,只有这样的系统才不会有新垃圾的产生。同时停顿保证了系统状态在某一个瞬间的一致性,也有利于更好的标记垃圾对象。因此在垃圾回收时,都会产生应用程序的停顿。

什么是Java垃圾回收器

串行回收器(Serial Collector)

串行回收器(Serial Collector)
单线程执行回收操作,回收期间暂停所有应用线程的执行,client模式下的默认回收器,通过-XX:+UseSerialGC命令行可选项强制指定。参数可以设置使用新生代串行和老年代串行回收器
年轻代的回收算法(Minor Collection)
把Eden区的存活对象移到To区,To区装不下直接移到年老代,把From区的移到To区,To区装不下直接移到年老代,From区里面年龄很大的升级到年老代。 回收结束之后,Eden和From区都为空,此时把From和To的功能互换,From变To,To变From,每一轮回收之前To都是空的。设计的选型为复制。
年老代的回收算法(Full Collection)
年老代的回收分为三个步骤,标记(Mark)、清除(Sweep)、合并(Compact)。标记阶段把所有存活的对象标记出来,清除阶段释放所有死亡的对象,合并阶段 把所有活着的对象合并到年老代的前部分,把空闲的片段都留到后面。设计的选型为合并,减少内存的碎片。

并行回收器(ParNew回收器)

并行回收器在串行回收器基础上做了改进,他可以使用多个线程同时进行垃
圾回收,对于计算能力强的计算机而言,可以有效的缩短垃圾回收所需的尖
际时间。
ParNew回收器是一个工作在新生代的垃圾收集器,他只是简单的将串行回收
器多线程快他的回收策略和算法和串行回收器一样。
使用XX:+UseParNewGC 新生代ParNew回收器,老年代则使用市行回收器
ParNew回收器工作时的线程数量可以使用XX:ParaleiGCThreads参数指
定,一般最好和计算机的CPU相当,避免过多的栽程影响性能。

并行回收集器(ParallelGC)

老年代ParallelOldGC回收器也是一种多线程的回收器,和新生代的
ParallelGC回收器一样,也是一种关往吞吐量的回收器,他使用了标记压缩
算法进行实现。
-XX:+UseParallelOldGC 进行设置
-XX:+ParallelCThread也可以设置垃圾收集时的线程教量。

Tomcat配置调优测试

Jmeter压力测试工具

JMeter是一款在国外非常流行和受欢迎的开源性能测试工具,像LoadRunner 一样,它也提供了一个利用本地Proxy Server(代理服务器)来录制生成测试脚本的功能,但是这个功能并不好用。所以在本文中介绍一个更为常用的方法——使用Badboy录制生成 JMeter 脚本。
垃圾回收机制算法分析-LMLPHP

垃圾回收机制算法分析-LMLPHP

测试串行吞吐量

-XX:+PrintGCDetails -Xmx32M -Xms32M
-XX:+HeapDumpOnOutOfMemoryError
-XX:+UseSerialGC
-XX:PermSize=32M
项目启动GC回收6次 吞吐量390

扩大堆的内存

-XX:+PrintGCDetails -Xmx512M –Xms532M
-XX:+HeapDumpOnOutOfMemoryError
-XX:+UseSerialGC
-XX:PermSize=32M

GC回收6次 445
结论 最大内存越大,吞吐量越高。

调整初始堆

-XX:+PrintGCDetails -Xmx512M –Xms512M
-XX:+HeapDumpOnOutOfMemoryError
-XX:+UseSerialGC
-XX:PermSize=32M

GC回收0次 492

并行回收(UseParNewGC)

-XX:+PrintGCDetails -Xmx512M –Xms512M
-XX:+HeapDumpOnOutOfMemoryError
-XX:+UseParNewGC
-XX:PermSize=32M

GC回收0次 吞吐量452

并行合并回收(UseParallelGC)

-XX:+PrintGCDetails -Xmx512M -Xms256M
-XX:+HeapDumpOnOutOfMemoryError
-XX:+UseParallelGC
-XX:+UseParallelOldGC
-XX:ParallelGCThreads=8
-XX:PermSize=32M

GC回收0次 吞吐量

调优总结

初始堆值和最大堆内存内存越大,吞吐量就越高。
最好使用并行收集器,因为并行手机器速度比串行吞吐量高,速度快。
设置堆内存新生代的比例和老年代的比例最好为1:2或者1:3。
减少GC对老年代的回收。

10-03 21:30