|
|
对于基本类型变量来说,因为都被分配在内存栈中,因此释放不是问题,而且都会被及时地释放。但对于引用类型来说,就不一样了。 Java提供了基本的对象内存回收机制-垃圾回收器。下面看看如何工作:
首先我们必须了解一点,引用类型的变量和基本类型的变量一样,都是被分配到内存栈里的,只是引用类型的变量在栈中保存的是
一个引用地址(指针),该引用地址所指的堆内存就是实际的对象存放区。
Java的垃圾回收器对于Java程序来说是外部程序,是独立运行的,因此必须有一种机制,让垃圾回收器知道哪些对象(堆中)
是不再被用的,最简单的方法当然是对对象引用计数:
一个对象被一个对象变量引用,其对象引用计数就加1,如果一个对象的引用变量(在栈中)超出生存期,被释放时,对象引用计数
就减1,这样,垃圾回收器就可以根据对象引用计数来判断对象是否可以被收回。看起来这种方法确实比较简单,但实际上,
这种方式还是有很多问题的:
1)如果对象变量都在栈中,上述机制当然没问题。但实际上对象变量可以是另一个对象的成员,而且对象本身也可以包含其它
对象类型的成员变量,这样就会形成一个复杂的引用关系网,这个引用关系网还可能会包含循环引用的情况,就会很容易导致一
些对象在整个程序运行期间都不会被回收,从而产生大量的内存泄露;
2)同步问题。垃圾回收器工作时,如果程序也在工作,也在分配或操作对象,比如一个对象的引用计数虽然为0,垃圾
回收器回收该对象,但同时,这个对象又被引用到一个新的对象变量,就会产生不可预知的错误。为了防止这种冲突,垃圾回
收器工作时程序就必须停止工作。这就会带来另外一个问题,程序运行效率降低。
现在这种利用对象引用计数方式的垃圾回收方式已经很少单独使用。
另外一种方法是采用对象跟踪技术的方法:
垃圾回收器工作时,从程序栈内存中的引用变量开始,遍历对象引用,标记对象可达。那么不可达的对象都可以回收掉。
这种方法解决了循环引用的问题,回收效率比较高,但也同样有以下问题:
1)没有解决垃圾回收器和程序之间的同步问题,垃圾回收器工作期间程序必须停止运行;
2) 每次垃圾回收时,都需要遍历所有的对象,用时会比较长;
当然还有很多垃圾回收策略,大家可以搜一下,虽然垃圾回收对于程序员来说,大部分时间是透明的,但理解这些机制,其实也可以
|
|