1 碎片整理:整理内存碎片
2 垃圾回收:以某种算法发现垃圾,并使用某种算法清除垃圾。
JVM常见的垃圾发现算法包括引用计数和追踪。其中, 引用计数就是为每个对象维护一个数字,这个数字记录了当前对象被引用的次数。当这个数字变为0的时候,说明该对象可以被垃圾回收了。但是引用计数无法发现那些循环引用的垃圾对象,比如垃圾对象a和垃圾对象b,两者互相引用,这个时候,虽然他们都是垃圾,但由于引用计算都是1,因此无法被发现。
此时,可以使用 追踪算法,JVM会维护一个从根节点开始的对象引用图,当需要垃圾收集的时候,会从根节点开始追踪。能追踪到的对象会被打上标记。当追踪结束的时候,还没有被标记的对象可以被回收。
下面介绍一个典型的分代垃圾收集算法:
在这种垃圾收集机制下, jvm的堆区被分为young代,old代和永久代。这里主要讨论young代和old代。如图所示:(年轻代包括Eden,和Survivor0,survivor1)
![](http://dl2.iteye.com/upload/attachment/0116/6279/13db50bb-1f28-30dc-955f-46ee2c7e0d07.png)
![](http://dl2.iteye.com/upload/attachment/0116/6281/aeedcec2-0920-364b-b59a-05bd5a32c2be.png)
当对象创建的时候,首先被放到Eden中(很大的对象有可能直接到old中),随着不断有对象被放入,当Eden满的时候,就会发生一次minor gc.在垃圾回收之前,JVM会使用垃圾发现算法,发现那些活着的对象(young代中活着的对象很少),然后将他们复制到S0区(如果S0放不下,会放到old代中),接着将Eden清空。
当再有对象被创建的时候,会放到Eden区中(很大的对象有可能直接到old中),当Eden满的时候,会发生一次minor gc.在垃圾回收之前,JVM会找出Eden和S0中活着的对象,然后将他们复制到S1中(如果S1放不下,会放到old代中),接着清空Eden和S0.
当再有对象被创建的时候,会放到Eden区中(很大的对象有可能直接到old中),当Eden满的时候,会发生一次minor gc.在垃圾回收之前,JVM会找出Eden和S1中活着的对象,然后将他们复制到S0中(如果S0放不下,会放到old代中),接着清空Eden和S1.
大家会发现,S0和S1中总有一个是空着的。当一个对象经历了多次gc(达到一定的阈值)仍然活着的时候,JVM就会考虑把他们放到old代中去。
我们需要做的就是使JVM尽可能少的发生old代的full gc.适当的发生young代的minor gc.因为在young中活着的对象很少,在gc前需要复制的对象很少。而在old中活着的对象很多,在gc前需要复制的对象很多,因此full gc会影响性能。