分享
 
 
 

漫谈Java(二)-- GC详解

王朝java/jsp·作者佚名  2007-05-30
窄屏简体版  字體: |||超大  

1.前言

Garbage Collector, 简称GC, 虽然不是Java的首创,但确实经由Java发扬光大. 正是有了GC机制,很多的Java程序员已经不再关心程序的内存问题,也体会不到了C/C++程序员的苦与乐. 但是, 在做一些较低层的模块或是一些较大型的应用时候, GC知识还是必不可少的. 笔者曾经参与的一个大型系统, 上线后系统一直运行良好,随着业务的发展,用户数也直接上升.终于当用户数到达了200万的时候, 一个跟用户数据打交道的子系统出现了重大的问题, 几乎所有的CPU时间都被用来进行垃圾回收, 系统近乎瘫痪. 这个例子说明了内存管理和合理运用GC的重要性.

2.内存模型

要弄清楚GC机制,首先要对Java的内存模型有所了解. 下图是JDK1.4虚拟机规范的内存模型

堆和栈是JVM中最重要的两个内存区域。每一个java 线程都拥有自己的内存栈,用来存放局部变量和返回值,这同传统的C语言十分类似。栈是在线程启动的时候分配的。而所有的线程都共享一个内存堆,所有运行时的内存分配都在堆上进行,换句话说,所有的对象都是在堆上创建的。堆是在JVM启动的时候分配的,它的空间由GC控制.

Java的内存分配有三种:

从静态存储区域分配。内存在程序编译时就分配好了,比如静态变量

在栈上创建。各种原始数据类型的局部变量都是在栈上创建的,当程序退出该变量的作用范围的时候,这个变量的内存会被自动释放。

在堆中创建。对象(包括数组)都是在堆中创建的。程序在运行的时候用new关键字来创建对象,对象创建时会在堆中为其分配内存。

3. GC Performance Tuning

在我们的实践中, 常常会根据系统的实际情况,选用不同的GC collector,配合不同的参数来进行性能调整,这是一门专门的技术,称为GC Performance Tuning. Sun公司甚至有专门这样的tuning服务提供给一些客户.接下来笔者将结合自己的经验,详细谈谈如何进行tuning.

3.1 分代复制算法

从JRE1.3开始, GC都采用了分代复制算法,这个算法根据对象的生存期将对象分成两代,新创建的对象在年轻代(Young Generation),当年轻代的内存分完的时候,GC将年轻代中少数尚未死亡的对象复制到另一块年老代(Tenured Generation),然后直接更新年轻代的指针,这个动作称为次要收集(minor collection),一次次要收集的时间取决于年轻代中存活的对象的数目,当年轻代中的对象绝大部分已经死亡的话,次要收集速度很快。当年老代的内存分完的时候,GC会进行一次主要收集(major collection),因为采用了标记收集, 这个动作很慢。所以我们Tuning的策略基本上来说就是尽量减少主要收集的次数。

3.2 Tuning的指标

Tuning的目的是提高性能,但性能指标是有很多种的, 不同的情况下对不同的指标有不同的要求. 因此,在开始Tuning之前,我们要先弄清楚究竟是要提高哪些指标,而不仅仅是一个模糊的概念-“提高性能”.

吞吐量(Throughput)是指没用在GC上的时间比例,中断(Pause)是当GC时,程序没有响应的时间。这是衡量GC性能的两个主要指标,不同的应用对于这两个指标要求是不一样的,所以调优的策略也就不一样。此外还有其它指标,Footprint,影响着可伸缩性(scalability),灵敏度(Promptness),指从一个对象死亡到它占据的内存可用的时间间隔。通常来说,吞吐量跟年轻代的大小成正比,其它指标跟年轻代成反比。一般情况下,一个generation的大小不会影响到另外一个generation的收集频率和中断时间.

3.2 GC Collector

从JRE1.4开始, 虚拟机提供四种collector以供实际选用,除了Default Collector之外,还有throughput Collector, Concurrent Collector和Incremental Collector.

Throughput Collector, 顾名思义,是为了追求最大吞吐量而设计的, 可以通过参数 –XX:+UseParallelGC指定. 它对年轻代采用了并行收集的算法, 使用多个线程来进行minor collection. 实践经验是当只有一个CPU时,使用它反而会比default collector慢,因为有线程同步的开销。当有两个CPU的时候,跟Default Collector差不多。当有三个或以上CPU时,效果会比较明显。当有多个CPU且需要提高throughput的时候我们会尝试使用它.这个collector还有几个相关的参数可以进行tuning. -XX:ParallelGCThreads=<desirednumber>,用于指定线程的数量; -因为每一个线程会保留一部分tenure来进行promotion,因此在每一部分tenure的边界会产生碎片. 使用-XX:+UseAdaptiveSizePolicy可以统计垃圾收集的这些相关信息, -XX:+AggressiveHeap让JVM自动根据机器的内存和CPU数优化各种参数,通常内存会使用机器的最大物理内存。

Concurrent Collector是为了追求最小pause而设计的,通过-XX:+UseConcMarkSweepGC指定。它对年老代使用并发收集的算法,即可能地让收集跟主程序的执行并发。通常,当程序拥有long-lived的对象(意味着tenure大),且在多CPU机器上跑的时候比较适用。这个collector第一次pause的时候,终止所有application的线程,一个线程进行收集。第二次pause的时候,终止所有application的线程,多个线程进行收集。余下的pause,一个线程进行收集,并且并发执行application线程。当机器的CPU空闲较多的时候可以采用,否则它会跟application抢系统资源。同时,因为并发操作中会产生碎片,所以tenure的保留空间要更大(因为没有好的方法去得知Eden和survivor中碎片的大小, 所以要有一个连续的剩余空间大于等于Eden的空间加上非空survivor中对象的空间,否则就有可能发生major collection)。当在并发收集的过程中,如果年老代满了,那么这时JVM会停下application线程,进行一次full GC,这是一个信号提示我们去调整参数。因为收集线程和application线程并发执行,所以可能出现收集线程认为是lived的,马上就会死亡,这种垃圾称为float garbage。这样就会影响灵敏度,粗略的规则是将tenure空间提高20%来避免这种情况。(因为tenure大了,在GC之前就会有更多的对象死亡)。float garbage在下一次GC时会被收集。我们还可以使用-XX:+UseParNewGC和-XX:+CMSParallelRemarkEnabled来进一步降低pause的时间

Incremental Collector,也是为了追求最小pause,通过-Xincgc来指定. 它通过每次minor collection时都对一部分tenure进行收集来达到这个效果,但是这样的整体throughput是最低的。当年老代较大,年轻代较小且只有一个CPU的时候可以考虑使用。当使用Default Collector并调整generation的大小不能满足pause的要求的时候,我们可以考虑它。有时它也会执行一次非递增的major collection来避免out of memory。

3.3 其他GC Performance Tuning的经验

尽量用缺省的GC,除非需要用到其它GC的特性

当应用有很多线程,且主机CPU跟内存都很多的时候,先尝试-XX:+AggressiveHeap

除非是年老代不够大或者pause时间太长,否则,尽可能给年轻代大一点

无论何时,年老代都要保证剩余空间大于等于Eden的空间加上非空survivor中对象的空间,否则就有可能发生major collection

当应用有较多的reflection的时候,就要考虑永久代

我们可以通过在程序闲时显式调用GC来改善性能

有的应用在Solaris 8以上,可以通过将线程绑定到一个轻量进程上来提高性能(LWPs)

当查看GC的log时,如果minor collection收集的垃圾与整体heap的垃圾的差额等于promotion的数量,如果数量较大,说明要调大年轻代

要同时使用Throughput Collector和Concurrent Collector的话,通过-XX:+UseConcMarkSweepGC-XX:+UseParNewGC指定(注意,不是-XX:+UseParallelGC,-XX:+UseConcMarkSweepGC和-XX:+UseParallelGC不能同时使用)

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有