设为首页收藏本站

                      LUPA开源社区

                       找回密码
                       注册
                      文章 帖子 博客
                      LUPA开源社区 首页 业界资讯 技术文摘 查看内容

                      Java垃圾回收机制

                      2018-9-5 11:16| 发布者: joejoe0332| 查看: 1854| 评论: 0|原作者: Rhys_Lee, AzureSora, 无若, 小小菜鸟鸡|来自: oschina

                      摘要: 自动垃圾回收是一种在堆内存中找出哪些对象在被使用,还有哪些对象没被使用,并且将后者删掉的机制。所谓使用中的对象(已引用对象),指的是程序中有指针指向的对象;而未使用中的对象(未引用对象),则没有被任何 ...

                      什么是自动垃圾回收?

                      自动垃圾回收是一种在堆内存中找出哪些对象在被使用,还有哪些对象没被使用,并且将后者删掉的机制。所谓使用中的对象(已引用对象),指的是程序中有指针指向的对象;而未使用中的对象(未引用对象),则没有被任何指针给指向,因此占用的内存也可以被回收掉。

                      在用 C 之类的编程语言时,程序员需要自己手动分配和释放内存。而 Java 不一样,它有垃圾回收器,释放内存由回收器负责。本文接下来将介绍垃圾回收机制的基本过程。

                      第一步:标记

                      这个过程的第一步叫做标记。这一阶段,垃圾回收器识别哪些内存正在使用,哪些内存未被使用。

                      被引用的对象以蓝色展示。未被引用的对象以金黄色展示。在标记阶段,所有对象都需要扫描并做出判断。如果系统中的所有对象都必须扫描到,这将是一个非常耗时的过程。

                      第二步:清除

                      这一步会删掉标记出的未引用对象。

                      内存分配器会保留指向可用内存的引用,以供分配新对象。

                      压缩

                      为了提升?#38405;埽?#21024;除了未引用对象后,还可以将剩下的已引用对象放在一起(压缩),这样就能更简单快捷地分配新对象了。

                      为什么使用分代垃圾回收?

                      如前所述,标记并整理所有JVM里的对象,效率是很低的。随着越来越多的对象被分配,对象列表不断增长,导致垃圾回收时间越来越长。然而,根据应用程序的经验分析,大多数的对象都是短命的。

                      下面是这类数据的一个例子。Y轴表示分配的字节数,X轴表示随着时间分配的字节数。

                      正如你所看到的,随着时间的推移,仍然存活的对象越来越少。?#29575;?#19978;,大多数对象的生命周期?#24049;?#30701;,如图左侧较高的值所示。

                      JVM 分代

                      根据之前的规律,就可以用来提升 JVM 的效率了。方法是,把堆分成几个部分(就是所谓的分代),?#30452;?#26159;新生代、老年代,以及永生代。

                      新对象会被分配在新生代内存。一旦新生代内存满了,就会开始对死掉的对象,进行所谓的小型垃圾回收过程。一片新生代内存里,死掉的越多,回收过程就越快;至于那些还活着的对象,此?#26412;?#20250;老化,并最终?#31995;?#36827;入老年代内存。

                      Stop the World ?#24405;?/strong> —— 小型垃圾回收属于一种叫 "Stop the World" 的?#24405;?#22312;这种?#24405;?#21457;生时,所有的程序线程都要暂停,直到?#24405;?#23436;成(比如这里就是完成了所有回收工作)为止。

                      老年代用来保存长时间存活的对象。通常,设置一个阈值,当达到该年龄时,年轻代对象会被移动到老年代。最终老年代也会被回收。这个?#24405;?#25104;为 Major GC。

                      Major GC 也会触发STW(Stop the World)。通常,Major GC会慢很多,因为它涉及到所有存活对象。所以,对于响应性的应用程序,应该尽量避免Major GC。还要注意,Major GC的STW的时长受年老代垃圾回收器类型的影响。

                      永?#20040;?/strong>包含JVM用于描述应用程序中类和方法的元数据。永?#20040;?#26159;由JVM在运行时根据应用程序使用的类来填充的。此外,Java SE类库和方法也存储在这里。

                      如果JVM发现某些类不再需要,并且其他类可能需要?#21344;洌?#21017;这些类可能会被回收。

                      分代垃圾回收过程

                      既然已经了解了为什么将堆分成不同的代,现在就该看看这些?#21344;?#21040;底是如?#35859;?#20114;的。下面的图片展示了JVM中对象分配和老化的过程。

                      首先,任何新对象都在Eden区分配。两个survivor区都是空的。

                      当Eden区满了,触发一次Minor GC。

                      被引用的对象被移动到第一个Survivor区,未被引用的对象会在Eden区清除时一并删除。

                      在下一次Minor GC中,Eden区也会做同样的操作。删除未被引用的对象,并将被引用的对象移动到Survivor区。然而,这里,他们被移动到了第二个Survivor区(S1)。此外,第一个Survivor区(S0)中,在上一次Minor GC幸存的对象,会增加年龄,并被移动到S1中。待所有幸存对象都被移动到S1后,S0和Eden区都会被清空。注意,Survivor区中有了不同年龄的对象。

                      在下一次Minor GC中,会重复同样的操作。?#36824;?#36825;一次Survivor区会交换。被引用的对象移动到S0,。幸存的对象增加年龄。Eden区和S1被清空。

                      此幻灯片演示了 promotion。 在较小的GC之后,当老化的物体达到一定?#21738;?#40836;阈值(在该示例中为8)时,它们从年轻一代晋升到老一代。

                      随着较小的GC?#20013;?#21457;生,物体将继续被推广到老一代?#21344;洹?/p>

                      所以这?#36127;?#28085;盖了年轻一代的整个过程。 最终,将主要对老一代进行GC,清理并最终压缩该?#21344;洹?/p>


                      酷毙

                      雷人

                      鲜花

                      鸡蛋

                      漂亮
                      • 快毕业了,?#36824;?#20316;经验,
                        找份工作好难啊?
                        赶紧去人才芯片公司磨练吧!!

                      最新评论

                      关于LUPA|人才芯片工程|人才招聘|LUPA?#29616;?/a>|LUPA教育|LUPA开源社区 ( 浙B2-20090187  

                      返回顶部
                      双色球中奖图片