按代的垃圾收集机制, 主要分为三种:
复制算法,空间被分为等大的两块,从根开始访问每一个关联的活跃对象,将空间 A 的活跃对象全部复制到空间 B,然后一次性回收整个空间 A,优点:只访问活跃对象,将所有活动对象复制走之后就清空整个空间,不用去访问死对象,所以遍历空间的成本较小,缺点:需要巨大的复制成本和较多的内存; 标记清除算法,从根开始访问所有活跃对象,标记为活跃对象。然后再遍历一次整个内存区域,把所有没有标记活跃的对象进行回收处理,优点:不需要额外的空间,缺点:较长的 GC 暂停时间,较大的扫描时间开销,产生较多的空间碎片; 标记清除整理算法,综合上两种算法的优点,先标记活跃对象,然后将其合并成较大的内存块。
代的划分:
- 年轻代:新创建的对象分配在此,研究表明,大部分程序所产生的对象都在此消亡,几乎所有的收集器为年轻代使用复制算法,年轻代又被划分为 1 个伊甸园区(Eden)和 2 个存活区(Survivor)用来实施复制算法; 也称Minor Collection,基于大多数对象Die Young的原则
- 年老代(Tenured):从年轻代存活下来的对象被复制到年老代,主要实施标记清除或标记清除整理算法;也称Major Collection, Full GC. 该过程会比较慢因为会遍历所有的Live 对象。
- 持久代(Permanent):装载的类数据和方法存储于此,无可消亡对象。
基于JVM层的性能调优思路大概是:
1. 对程序进行profiling, 主要考虑方法调用过程,花费的时间等
2. dump出heap或者实时监控分析 对象大小,引用关系
3. 启动Java程序时打开 -verbose:gc, 分析GC执行情况,执行前后Heap中对象在图上显示有什么pattern(如果有图形显示的工具的话)
根据分析结果检查线程,死锁,内存泄漏的蛛丝马迹。最后可以考虑对JVM启动参数进行调整,这个会改变GC的算法及内存(heap)分配情况
单处理器时基本是基于Generation的Copy算法或者Mark-Sweep-Compact算法;多处理器时考虑并行GC因此可以指定更多的GC策略,一个处理器做GC,另一个继续运行Applicaiton。这样不用象单处理器一样GC时Applicaiton Pause住。