代码改变世界

Java内存回收(垃圾回收)机制总结

2014-06-19 22:11  每天努力一点点  阅读(1560)  评论(0编辑  收藏  举报

一、背景:

Java程序员编写程序时,对于新建的对象,当不再需要此对象时,不必去释放这个对象所占用的空间,这个工作是由Java虚拟机自己完成的 ,即内存回收或垃圾回收。

二、如何知道一个对象所占用的空间可以回收了呢?

1.常用的一种算法是引用计数法,如果一个对象的引用为0了,那就可以回收了。但是对于这种方法致命缺陷,当对象之间存在循环引用的时候,A引用B,B引用A,这样A和B的引用就一直不会为0,那就无法回收了。

2、Java采用的算法为根搜索算法,以一系列GC Roots为起点,向下搜索,如果存在引用,则对象依然在用,不能回收;如果不存在引用,则可以回收。

可以作为GC Roots的有如下几种:

a、虚拟机栈(栈帧中的本地变量表)中的引用的对象
b、方法区中的类静态属性引用的对象
c、方法区中的常量引用的对象
d、本地方法栈中JNI的引用的对象

三、java堆栈内存结构划分:

1.新生代(Young Generation):又细分为三块(eden,S0,S1)

 新的对象总是在新生代创建。

2.老年代(Old Generation)

 在新生代存放一定时间之后,在新生代空间不够时,对象会被移到老年代。

3.永久代(Permanent)

用于存在类信息。对于动态生成的类,后续不会再使用到,所以可以进行回收。

四、为什么采用分代(区)的方式来进行堆栈空间的管理呢?

因为不同的对象存活时间不同,多数对象存活时间很短,少数对象存活时间很长。如果每次回收都遍历所有对象,效率将会非常低。按对象存活时间长短,划分不同的内存区域来管理对象,对不同的区采用不同的回收算法。

五、主要的空间回收算法:

1.复制算法

对于新生代,划分了eden/S0/S1三块区域,开始对象创建在eden区域上。

下面来描述一下可能的操作过程,各个java虚拟机的实现会有差异,下面是大致进行阐述。

第一次清理的时候,将可以清除的对象删除,将要保留的对象都复制到S0区域,eden区域清空,对象年龄标记增长1;

第二次清理的时候,将可以清除的对象删除,将要保留的对象从eden和S0都复制到S1,并将eden和S0都清空,对象年龄标记增长1;

第三次清理的时候,将可以清除的对象删除,将要保留的对象从eden和S1都复制到S0,并将eden和S1都清空,对象年龄标记增长1;

后续清理的时候,以此重复上面的步骤,当对象的年龄达到一定值时,就被移到老年代中去。

对于上面的过程,可以通过jvisualvm观测到,会发现eden和S0同时被清空,对象转移到S1,或eden和S1同时被清空,对象转移到S0.

下面给出两张jvisualvm的截图:

时刻1:

时刻2:

时刻3:

通过上面三张图对比可以看到,当S0被占用时,S1就是空的;S1被占用时,S0就是空的,这也就印证了上面算法描述里说的信息。

2.标记清除算法(包括整理)

因为老年代中,可以回收的对象很少,所以触发对老年代的回收几率也比较低,对于老年代也不采用复制算法,因为那样空间利用率比较低,而是采用标记清除(整理)方式。如果对应对象的空间可以回收了,就进行回收,并对对象存储位置进行移动,将对象移到到一起,避免中间存在空隙,便于后续内存分配。

六、几个可以用于指定java虚拟机各个块大小的参数:

-XX:PermSize       设置永久代初始大小(样例:-XX:PermSize=40M)
-XX:MaxPermSize    设置永久代最大大小(样例:-XX:MaxPermSize=100M)
(注:java对此参数值限制,具体限制可能因操作系统、CPU/内存差异而又不同,在Window7上测试时,最小值为12M;不能设置为奇数,必须为偶数)

-XX:NewSize        设置新生代初始大小(样例:-XX:NewSize=10M)
-XX:MaxNewSize     设置新生代最大值(样例:-XX:MaxNewSize=20M)
-XX:SurvivorRatio  设置新生代中eden和survivor区(S0/S1)的比例,通过验证,实际大小比例为该值*1.2,如设置为8,则eden空间大小/S0=8*1.2(样例:-XX:SurvivorRatio=8)
-Xmx               设置堆栈最大值,包括老年代和新生代,不包括永久代(样例-Xmx100M)
-Xms               设置堆栈初始大小(样例:-Xms50M)
-XX:NewRatio       老年代和新生代的大小比例,设置此参数时不能设置MaxNewSize,否则此参数失效(样例:-XX:NewRatio=2)


参考资料:

http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html

http://www.open-open.com/lib/view/open1380593930103.html

http://blog.csdn.net/time_hunter/article/details/12405127