Java垃圾回收(1)

来源:互联网 发布:Python开发安卓 编辑:程序博客网 时间:2024/06/03 15:37

本文是关于垃圾回收(GC)系列的第一篇文章。我希望通过这一系列的课程能够覆盖一些垃圾回收的原理和在hotspot虚拟机中的一些主要的垃圾回收器。本文仅仅只是描述什么是垃圾回收和不同垃圾收集器的共同元素。

为什么我们应该关心垃圾回收?

Java虚拟机为你管理内存,这虽然非常方便,但是默认情况下它可能不会开启最佳优化。通过理解垃圾收集背后的一些原理,你就可以更容易的调整你的收集器。一个常见的问题就是垃圾收集器的效率问题,也就是说你的程序花费多长时间执行程序代码而不是回收垃圾。另一个常见的问题就是应用暂停多长时间的问题。

关于垃圾回收有很多的谣言和传闻,因此详细的理解垃圾回收算法真的可以帮助避免陷入一些陷阱和圈套。此外,对于对计算机科学原理如何应用和使用感兴趣的人来说,JVM的内部机制是非常值得一看的。

stop-the-world是什么意思?

你的程序(在GC中称为mutator )在运行时分配对象,在某些时候heap需要被回收并且在hotspot上的所有收集器会暂停你的应用,stop-the-world这个术语就是用来表示所有mutator进程被暂停。

实现一个不需要暂停应用的垃圾收集器是可以的,Azul在Zing虚拟机中已经实现了一个非常高效而且无需暂停的收集器。本文我们不会去探讨这种收集器如何工作,但是如果你感兴趣并且想了解更多关于这种收集器的信息,你可以参见他的白皮书。

新生代和弱年代假设(The Young/Weak Generational Hypothesis)

简单的说:大多数被分配的对象在创建后会很快变得不可到达。这一概念在20世纪80年代通过分析了大量项目的内存分配和活跃模式得到验证。研究人员还发现不仅仅是大多数被分配的对象在创建后会很快变得不可到达,而且一旦他们的生命周期达到一个特定的点之后,他们就会存在很长一段时间。下面这幅图是来自SUN/Oracle的研究,此图通过直方图的形式展示对象的寿命情况。
这里写图片描述

堆(Heap)如何组织(How is Heap organised)?

新生代假设(young generational hypothesis)引出了分代垃圾回收(generational garbage collection)的概念,在这种垃圾回收中,堆被分成了很多个区域,每个区域所放置的对象和他们的年龄(对象生成时间)相关。基于分代垃圾收集概念的这些垃圾回收器(G1除外)都有一个共同点,即堆(Heap)被组织到不同的空间中。
这里写图片描述
当对象被初始分配时,如果合适,他们就会被存储在Eden空间中。如果一个对象在一次垃圾回收中幸存下来,那么最终它就会被移动到幸存者(survivor)空间。当这些对象在幸存者(survivor)空间存活一段时间(一个老年代时间阈值)之后就会被移动到老年代(tenured )空间。回收这些空间的算法特性因收集器而异。

空间的分隔是有很多好处的,因为它允许你在不同的空间中使用不同的算法。有些GC算法在大多数对象已经不可达的情况下非常有效,而有些GC算法是在大多数对象可达的情况下非常有效。由于分代假设(generational hypothesis)通常是在Eden和survivor空间中收集大多数不可达的对象并且在老年代(tenured)空间中大多数的对象都是可达的。

也有永久(permgen)或者永久代(permanent generation)。这个特殊的空间主要是控制和Java语言本身相关的一些对象。比如说这里保存了加载类的信息。永久代在Java8中已经被移除,取而代之的是元空间(metaspace)。

几种垃圾回收器

hotspot虚拟机实际上有很多不同的垃圾回收器。每个垃圾回收器都有不同的性能特点并且或多(或少)适用的任务。一些比较关键的垃圾回收器如下:

Parallel Scavenge (PS):最近发布的JVMs的默认收集器。 stops-the-world是为了垃圾回收,但是是parallel中的回收(例如使用多线程)。

Concurrent Mark Sweep (CMS):这种收集器有很多个阶段,其中包括stop the world,但是在很多阶段这种收集器回收垃圾时都是和程序同时运行。

Incremental Concurrent Mark Sweep (iCMS):CMS的一种变体,这种收集器的设计主要是为了减少应用程序的暂停。

Garbage First (G1):最近非常稳定的新型收集器,使用量正在慢慢的上涨。

原文:https://www.javacodegeeks.com/2013/06/garbage-collection-in-java-1.html