首页 > 代码库 > Java GC 小结

Java GC 小结

  很早就想对Java的GC做点小总结,一直没有时间,最近看了下java paper上的java gc文章,觉得不错,读了读,顺便做下总结。

  java paper的GC文章地址,里面有很多java技术文章,写的都不错。

1、Java GC 简介

JVM的垃圾回收机制使开发者不必过多考虑内存的申请与释放,这样降低了软件开发的成本和语言的学习成本。

不同的JVM对GC的实现是不同的,目前Oracle维护着两种JVM,JRockit JVM,HotSpot JVM。

本文讨论的JVM是居于HotSpot的JVM。

1、运行时数据区域

方法区、Heap内存,Java Stack, PC Registers,本地方法栈

(以下图片均来自网络)


2、执行引擎

JIT Compiler, Garbage Collector


2、Heap Memory

在运行时,java对象的实例均被分配在heap内存中。当对象不被引用的时候,会被垃圾回收器标记为eviction,然后回收,最后释放在heamp中所占用的空间。

Java Heap Memory 分为三个区域:
1、Young Generation

1、Eden  任何实例进入运行时的内存区域都是从Eden进入的
2、S0 存活久一点的实例就可以从Eden进入到S0
3、S1 存活更久的实例从S0进入S1
2、Old Generation

tenured (终身制的),实例从S1晋升到终身制区域
3、Permanet Generation

包含元数据信息,如class,method的detail信息


翻译一段来自java paper的Heap介绍:

Eden Space:
每当一个实例被创建,就会分配到eden空间。

Survivor Space (S0 and S1):
作为minor GC的一部分,对象如果还在被引用的,就会从移动到S0.

在minor GC时,如果对象没有被引用了,该对象就会被标记为要驱逐出内存中的对象。

Old Generation:

老年代是heap memory的逻辑部分,当垃圾收集器进行minor GC的时候,S1中还在存活的对象实例将从S1 移动 到 Old, 在S1中失去引用的部分,将被标记为从内存中驱逐。

Major GC:
老年代中的对象在进行Major GC时,那些失去引用的对象将被标记为从内存中驱逐。

Memory Fragmentation:
内存片段:当实例从heap memory中删除时,被删除后内存位置可以供新分配的对象使用,内存碎片需要被整理成连续的空间,内存碎片整理,从而能进行快速的分配内存空间。
在驱逐对象实例和恢复内存空间之前,要对对象实例调用finalize()方法来对 该对象实例持有的资源进行释放。
尽管finalize()方法一定在恢复内存空间前执行,但是顺序是无序的,是没有规定时限的。对象多实例之间的释放顺序不能提前决定,它们甚至可能是并行的进行。

3、GC 过程

Young 和 Old 的关系是 晋升关系

联想起来,其实可以这样打个比方,就是学生上学的场景:

Heap Memory中的GC就是上学的问题。

我们把这几个区域比作学校。实例比作学生

Young
Eden    S0    S1     
小学    初中  高中

Old
大学

Permanet
学生元信息库


描述GC的过程就很通俗易懂啦。

判断是否晋升,是否标记释放,可以用reference来判断。那么:

still referenced  仍然被引用的 (就是仍然愿意学习学生)
dereferenced  失去引用的(就是不愿意学习的学生)

MinorGC:(发生在Young内)

1、比如一个学生刚上学,那么他肯定首先分配到小学,即Eden。

2、如果在小学里还想继续学习的学生,即still refernced的学生,就会晋升到初中S0进行学习。不想学习的学生,即dereferenced 会被标记为毕业,会被垃圾回收。

3、如果在初中里还想继续学习的学生,即still refernced的学生,就会晋升到高中S1进行学习。即dereferenced 会被标记为毕业,会被垃圾回收。


MajorGC:(发生在Old)

当在高中毕业后S1,还想继续学习的,那么就会被晋升到大学Old。

发生MajorGc时,Old中会回收失去引用的实例,还被引用的将不被回收,还在Old大学里继续学习。当大学里装的学生太多了,就会触发OutOfMemoryError了。

(以下图片来自网络)


4、对象的回收

什么情况下对象会被回收?
 
Strong Reference     Not eligible for garbage collection  - 强引用的对象实例不会被回收
Soft Reference     Garbage collection possible but will be done as a last option - 软引用的对象实例可能会被回收,但是一定是在不得不回收的情况下才回收。
Weak Reference     Eligible for Garbage Collection - 弱引用的肯定会被回收
Phantom Reference     Eligible for Garbage Collection - 幽灵引用的肯定会被回收


1、声明后从来都没使用的对象,编译器会自动给该对象置为null,会被编译器标记为eviction。
编译器会将那么不会在后续使用的对象,在运行时之前提前将其提前回收。

2、典型的一个例子,一个实例的所有属性都存在register中,访问实例的属性值是从register中读取的,如果这个实例在未来不会将属性值写回实例,那么该实例还是会被标记为驱逐。

3、null值赋给实例,如果该实例没有其它实例的引用,则会被标记回收。

4、当finalize方法被调用,JVM会释放在那个线程的所有同步锁。

5、总结

  JVM是一套标准,有很多种实现,我们最常接触的是HotSpot JVM,对于不同的JVM,垃圾回收器的实现也不同。

  JVM中主要是分为运行时数据区域 和 执行引擎。

  Heap Memory中被划分为Eden,S0,S1,Old,Perm

  GC的过程就是这Eden到S0,S0到S1,S1到Old的晋升过程,分为minorGC 和 MajorGC(FullGc)。

  强引用对象不会被垃圾回收,软引用一般情况下不会被回收,实在不能回收时最后才会被回收。 弱引用和幽灵引用的都会被回收。


——EOF——

原创文章,转载请注明出自:http://blog.csdn.net/oopsoom/article/details/40348125

Java GC 小结