关于java 垃圾回收的理解
垃圾回收分为两大步骤:识别垃圾 和 回收垃圾
识别垃圾有两大基本方法
1.计数器法
每个对象有一个相应的计数器,统计当前被引用的个数,每次被引用或者失去引用都会更新该计数器。
优点:识别垃圾快,只需判断计数器是否为零。
缺点:增加了维护计数器的成本,无法在对象互相引用的情况下识别垃圾
因此,适用于对实时性要求非常高的系统。
2.追踪法
从根对象(例如局部变量)出发,逐一遍历它的引用。若无法被扫描到,即认定为垃圾
实际情况中一般采用该方法。
回收垃圾最重要的是要最大限度地减少内存碎片。
两种通常的方法:
1.移动活对象覆盖内存碎片,使对象间的内存空白增大。
2.拷贝所有的活对象到另外一块完整的空白内存,然后一次释放原来的内存。
通常第二种方法能够最大的减少内存碎片,但是缺点是在拷贝过程中会终止程序的运行。
引入分级的概念,通常一个程序中大部分对象的生命周期很短,只有小部分的对象有比较长的生命。而恰恰使得拷贝方法性能打折扣的是重复拷贝那些长命的对象。因此,把对象分成几个级别,在低级别呆到一定时间就将其升级。相应地越高级别,回收的次数越少。最理想的情况是,每次回收最低级别的对象全部失效,一次性就可以回收该级别所有内存,提高效率。同时,由于每次只回收一个级别,不需遍历所有对象,控制了整个回收的时间。
由于垃圾识别是通过识别引用来达到,为了增加程序对垃圾回收的控制。提供了引用对象的概念,细化了引用的类型,分别是StrongReference,SoftReference, WeakReference, PhantomReference。其中强引用就是普通的java引用,其他三种类型相当于一个包装器,一方面使得垃圾回收器区分引用类型做不同的处理,另一方面程序通过他们仍然可以得到强引用。
这三种弱类型的类的结构图:
因此一个对象在它的生命周期可能有以下几种状态:strongly reachable,softly reachable,weakly reachable,resurrectable,phantom reachable,unreachable。
这三种弱引用的应用场合:
public static void main(String[] args) throws Exception{byte[] b = new byte[1024 * 1024 * 5];SoftReference sr = new SoftReference(b);b = null;byte[] b2 = new byte[1024 * 1024 * 5];byte[] b3 = new byte[1024 * 1024 * 5];if (sr == null){System.out.println("1");}else if (sr.get() == null){System.out.println("2");}else{System.out.println("3");}}
你会发现在执行FullGC之后sr!=null,但sr.get()==null 10 楼 safrain 2011-05-07 lifeier 写道扯这些有什么鬼用,开发中又用不着。
有一些场合会用到的。 11 楼 Rooock 2011-05-08 关于java里的几种引用, 我觉得这篇文章言简意赅. 12 楼 jwx0925 2011-05-08 lifeier 写道扯这些有什么鬼用,开发中又用不着。
水平低,还用不到吧~ 13 楼 liuxuejin 2011-05-09 解释得实在有点简单 14 楼 laolinshi 2011-05-10 lifeier 写道扯这些有什么鬼用,开发中又用不着。
这只能说明你还停留在民工的水平。 15 楼 suhuanzheng7784877 2011-05-10 个人觉得垃圾回收的原理还是需要知道的啊~~~~
是这样的~~
有时候确实对象在内存中的状态、周期是需要知道的~
而且弱引用、软引用等等都是在一定场合下派得上用场的~~~
一旦应用报出了内存溢出的异常也好排错嘛~
呵呵~~
http://suhuanzheng7784877.iteye.com/blog/1000646
这个希望对LZ也能有所帮助~ 16 楼 葬雪晴 2011-05-11 lifeier 写道扯这些有什么鬼用,开发中又用不着。
鄙视这种自己不会,就乱喷的人。
补充一点,我理解的垃圾回收机制。
在JAVA语言里,有自动的回收机制,让我们能很轻松的不用去理会垃圾回收,而能轻松的编程。
不像C++一样,还要去析构,不去析构就会内存溢出然后头痛的很。
JAVA里的垃圾回收机制,用的是类似有向图的监控,当一个对象完全没有了指向这个对象的引用的时候,垃圾回收机制会帮忙回收。。。由于启动垃圾回收器需要花费资源,所以不是说你想启动就启动的。所以只能是建议System.GC()
所以很多新手就认为,都机器做了垃圾回收机制,我们不需要去管,其实那只是新手的一厢情愿。
JAVA也有内存溢出,在进行队列的删除的时候如果由于只是在标记位上删除,而数组本身的某个引用还是有对象的,于是这个引用永远都不会回收。于是会造成内存溢出。
哈哈,大家多多包涵