下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、上次讲到引用类型和基本类型由于内存分配上的差异导致的性能问题。那么今天就来聊一下和内存释放(主要是 gc)有关的话题。事先声明一下:虽说 sun 公司已经被 oracle 吞并了,但是出于习惯,同时也为了偷懒节省打字,以下仍然称之为 sun 公司。jvm 的内存在 java 虚拟机规范中(具体章节请看“这里”),提及了如下几种类型的内存空间:栈内存(stack):每个线程私有的。堆内存(heap):所有线程公用的。方法区(methodarea):有点像以前常说的“进程代码段”,这里面存放了每个加载类的反射信息、类函数的代码、编译时常量等信息。原生方法栈(nativemethodstack):主
2、要用于 jni 中的原生代码,平时很少涉及。关于栈内存(stack)和堆内存(heap),已经在上次的帖子中扫盲过了,大伙儿应该有点印象。由于今天咱们要讨论的“垃圾回收”话题,主要是和堆内存(heap)有关。其它的几个玩意儿不是今天讨论的重点。等以后有空了,或许可以单独聊一下。垃圾回收机制简介其实 java 虚拟机规范中并未规定垃圾回收的相关细节。垃圾回收具体该怎么搞,完全取决于各个 jvm 的设计者。所以,不同的 jvm 之间,gc 的行为可能会有一定的差异。下面咱拿 sun 官方的 jvm 来简单介绍一下 gc 的机制。啥时候进行垃圾回收?一般情况下,当 jvm 发现堆内存比较紧张、不太够
3、用时,它就会着手进行垃圾回收工作。但是大伙儿要认清这样一个残酷的事实:jvm 进彳 fgc 的时间点是无法准确预知的。因为 gc 启动的时刻会受到各种运行环境因素的影响,随机性太大。虽说咱们无法准确预知,但如果你想知道每次垃圾回收执行的情况,还是蛮方便的。可以通过 jvm 的命令行参数“-xx:+printgc”把相关信息打印出来。另外,调用 system.gc()R 是建议 jvm 进彳 fgc。至于 jvm 到底会不会做,那就不好说啦。通常不建议自己手动调用 system.gc(),还是让 jvm 自行决定比较好。另外,使用 jvm 命令行参数-xx:+disableexplicitgc可
4、以让 system.gc(pp 起作用。谁来负责垃圾回收?一般情况下,jvm 会有一个或多个专门的垃圾回收线程,由它们负责清理回收垃圾内存。如何发现垃圾对象?垃圾回收线程会从“根集(rootset)”开始进行对象引用的遍历。所谓的“根集”,就是正在运行的线程中,可以访问的引用变量的集合(比如所有线程当前函数的参数和局部变量、当前类的成员变量等等)。垃圾回收线程先找出被根集直接引用的所有对象(不妨叫集合 1),然后再找出被集合 1 直接引用的所有对象(不妨叫集合 2),然后再找出被集合 2 直接引用的所有对象如此循环往复,直到把能遍历到的对象都遍历完。凡是从根集通过上述遍历可以到达的对象,都称为
5、可达对象或有效对象;反之,则是不可达对象或失效对象(也就是垃圾)。如何清理/回收垃圾?通过上述阶段,就把垃圾对象都找出来。然后垃圾回收线程会进行相应的清理和回收工作,包括:把垃圾内存重新变为可用内存、进行内存的整理以消除内存碎片、等等。这个过程会涉及到若干算法,有兴趣的同学可以参见“这里限于篇幅,咱就不深入聊了。分代早期的 jvm 是不采用分代技术的,所有被 gc 管理的对象都存放在同一个堆里面。这么做的缺点比较明显:每次进行 gc 都要遍历所有对象,开销很大。其实大部分的对象生命周期都很短(短命对象),只有少数对象比较长寿;在这些短命对象中,又只有少数对象占用的内存空间大;其它大量的短命对象
6、都属于小对象(很符合二八原理)。有鉴于此,从 jdk1.2 之后,jvm 开始使用分代的垃圾回收(generationalgarbagecollection)ojvm 把 gc 相关的内存分为年老代(tenured)和年轻代(nursery)、持久彳 t(permanent,对应于 jvm 规范的方法区)。大部分对象在刚创建时,都位于年轻代。如果某对象经历了几轮 gc 还活着(大龄对象),就把它移到年老代。另外,如果某个对象在创建时比较大,可能就直接被丢到年老代。经过这种策略,使得年轻代总是保存那些短命的小对象。在空间尺寸上,年轻代相对较小,而年老代相对较大。因为有了分代技术,jvm 的 gc
7、 也相应分为两种:主要收集(majorcollection)和次要收集(minorcollection)o主要收集同时清理年老代和年轻代,因此开销很大,不常进行;次要收集仅仅清理年轻代,开销很小,经常进行。gc 对性能会有啥影响?刚才介绍了 gc 的大致原理,那 gc 对性能会造成哪些影响捏?主要有如下几个方面:造成当前运行线程的停顿早期的 gc 比较弱智。在它工作期间,所有其它的线程都被暂停(以免影响垃圾回收工作)。等到 gc 干完活,其它线程再继续运行。所以,早期 jdk 的gc 一旦开始工作,整个程序就会陷入假死状态,失去各种响应。经过这些年的技术改进(包括采用分代技术), 从 jdk1
8、.4 开始, gc 已经比较精明了。 在它干活期间, 只是偶尔暂停一下其它线程的运行(从长时间假死变为暂时性休克)。遍历对象引用的开销试想如果 jvm 中的对象很多,那遍历完所有可达对象肯定是比较费劲的工作,这个开销可不小。清理和回收垃圾的开销遍历完对象引用之后,对垃圾的清理和回收也有较大的开销。这部分开销可能包括复制内存块、更新对象引用等等。几种收集器两个性能指标因为今天聊的是性能的话题,必然会提到衡量 gc 性能的两个重要指标:吞吐量(throughput)和停顿时间(pausetime)。吞吐量这个词不是很直观,解释一下:就是 jvm 不用于 gc 的时间占总时间的比率。吞吐量是越大越好
9、,停顿时间是越小越好。不同的应用程序对这两个指标的关注点不一样(后面具体会说),也就是所谓的“众口难调”。很多 jvm 厂商为了迎合“众口”,不得不提供多种几种垃圾收集器供使用者选择。不同的收集器,采用的收集策略是不一样的,下面具体介绍。串行收集器(serialcollector)使用命令彳 f 选项-xx:+useserialgc”指定。这种收集器是最传统的收集器。它使用单线程进行垃圾回收,对于单 cpu 机器比较合适。另外,小型应用或者对上述两个指标没有特殊要求的,可以使用串行收集器。并行收集器(parallelthroughputcollector)顾名思义,这种收集器使用多个线程进行垃
10、圾回收以达到高吞吐量。垃圾回收线程的数量通过命令行选项-xx:parallelgcthreads=n”指定。可以设置该数值以便充分利用多 cpu/多核。当使用命令行选项-xx:+useparallelgc”时:它会针对年轻代使用多个垃圾回收线程,对年老代依然使用单个线程的串行方式。此选项最早在 jdk1.5 引入。当使用命令行选项-xx:+useparalleloldgc时:它针对年轻代和年老代都使用多个垃圾回收线程的方式。不过此选项从 jdk1.6 才开始引入。并发收集器(concurrentlowpausecollector)使用命令彳 f 选项“-xx:+useconcmarksweep
11、gc指定。这种收集器优先保证程序的响应。它会尽量让垃圾回收线程和应用自身的线程同时运行,从而降低停顿时间。此选项从 jdk1.4.1 开始支持。增量收集器(incrementalcollector)自从 jdk1.4.2 以来,sun 官方就停止维护该收集器了。所以俺就节省点口水,不多说了。如何降低 gc 的影响?尽量减少堆内存的使用由于 gc 是针对存储在堆内存的对象进行的。咱们如果在程序中减少引用对象的分配(也就相应降低堆内存分配),那对于提高 gc 的性能是很有帮助滴。上次“字符串过滤实战”的帖子给出了一个例子,示范了如何通过降低堆内存的分配次数来提升性能。设置合适的堆内存大小jvm 的
12、堆内存是有讲究的,不能太大也不能太小。如果堆内存太小,jvm 老是感觉内存不够用,可能会导致频繁进行垃圾回收,影响了性能;如果堆内存太大,以至于操作系统的大部分物理内存都被 jvm 自个儿霸占了,那可能会影响其它应用程序甚至操作系统本身的性能。另外,年轻代的大小(或者说年轻代与年老代的比值)对于 gc 的性能也有明显影响。如果年轻代太小,可能导致次要收集很频繁;如果年轻代太大,导致次要收集的停顿很明显。jvm 提供了若干和堆内存大小相关的命令行选项,具体如下:-xms 设置初始堆内存-xmx 设置最大堆内存-xmn 设置年轻代的大小-xx:newratio=n 设置年轻代与年老代的比例为n-xx:newsize=n 设置年轻代大小为n一般情况下,jvm 的默认参数值已经够用。所以没事儿别轻易动用上述选项。如果你非调整不可,一定要做深入的性能对比测试,保证调整后的
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025土地流转合同范文
- 养猪产业链一体化2025年度合作协议模板3篇
- 2025城市综合体物业租赁合同
- 2025服务合同香港及境外股市投资咨询服务协议
- 2025年度农村房屋产权转让及配套设施移交合同2篇
- 二零二五年度企业培训与发展公司管理服务协议3篇
- 二零二五年度农副产品电商平台入驻合作协议3篇
- 2025年度智能化公厕建设与运营管理承包施工合同书模板3篇
- 二零二五农村宅基地买卖与农村土地整治与生态保护合同
- 二零二五年度农民工工资支付委托及劳务合同管理协议
- 计量经济学知到智慧树章节测试课后答案2024年秋云南财经大学
- 乡镇卫生院院长工作职责
- 屋顶分布式光伏发电项目施工重点难点分析及应对措施
- 退休人员返聘劳动合同三篇
- 中华人民共和国安全生产法知识培训
- 食品工艺学名词解释、简答题、填空题等
- 中医脑瘫课件教学课件
- 2024年新闻宣传新闻采编专业及理论知识考试题附含答案
- 河南省濮阳市清丰县多校2024-2025学年三年级上学期期中测试数学试题(无答案)
- 四川新农村建设农房设计方案图集川东南部分
- 瑞得RTS-820系列全站仪说明书(适用RTS-822.822A.822L.822R.822R .822R3)
评论
0/150
提交评论