java终结处理和垃圾回收

java中的对象,并非总是被垃圾回收,换句话说,
1.对象可能不被垃圾回收
2.垃圾回收并不等于c++中的析构函数
3.垃圾回收只与内存相关。

java中的finalize()方法需要一种特殊情况,即通过某种创建对象方式以外的方式为对象分配了存贮空间。之所以这样,是由于在分配空间时,可能采用了类似c语音的做法,而不是java的通常做法,这种情况主要发生在使用“本地方法”的情况下,本地方法,是一种在java中调用非java代码的方式。它仅支持c和c++,但可以调用其他语言写的代码,所以在java语言体系里,不需要过多的使用finalize()方法。


无论是垃圾回收还是终结,都不保证一定发生。如果jvm并未面临内存耗尽,他是不会浪费时间执行垃圾回收以恢复内存。所以,你必须实施清理。但是通常又不能指望finalize()方法,必须创建其他的一些方法去清理。不过,finalize()还是有一个有趣的用法,它并不需要依赖于每次都要对finalize()进行调用,这就是对象“终结条件”的验证。即,当对某个对象不再感兴趣,也就是它可以被清理了,那么这个对象应该处于某种状态,是他的内存可以被安全释放。有个简单的例子,见think in java p89.



垃圾回收器如何工作?

jvm采用一种自适应的垃圾回收机制,顾名思义他会根据存活的对象自动实现回收机制。这个取决于不同的jvm实现。这里的自适应一般分2种,

1.停止-复制(stop-copy),先暂停程序运行(所以不属于后台回收模式),然后将所有存活的内存对象从当前的堆中复制到另一个堆,没有被复制的全都是垃圾。当对象被复制到新的堆时,他们是一个挨着一个的 ,所以新堆保证紧凑排列,然后就可以按前述方法简单直接的分配新空间了。

当把对象从一处,搬到另一处,所有指向它的引用都需要修正。位于静态存贮或堆的引用,可以直接被修正,但是可能还有其他的引用,只有在遍历的时候才能被找到,类似于有一个表格,把旧地址映射到新地址。

对于这种回收机制,他的效率会降低,第一它要有2个堆然后在这2个之间来回操作,维护的空间比实际的多出一倍还多。某些jvm对这个问题的处理方式是,按需求从堆中分配出几块较大的内存,复制动作只是发生在这几块大内存之间。第二个问题是,程序稳定之后,可能只会产生少量垃圾甚至没有垃圾。这个机制下,仍会这样停止复制,并占用资源,进而导致浪费。于是,就有了第二种模式的垃圾回收方式。


2.标记-清扫(mark-sweep),sun公司早期版本的jvm使用了这一技术。对于一般用途,这种方式速度相当慢,但是你知道程序只产生少了垃圾甚至没有垃圾时,他的速度就很快了。因为需要被标记的对象少。

它的出发点,仍是从堆栈和静态存储出发,遍历所有引用,进而找出所有存活的对象。标记玩所有的对象后,清理动作开始执行。没有被标记的对象将被释放,不会发生任何复制动作。剩下的堆空间,是不连续的,垃圾回收器要是希望得到连续的空间,就得重新整理剩下的对象。于是,停止-复制(stop-copy)正好能达到这个目的。


所以垃圾回收器。实际上是这二者的结合使用。而jvm中有许多附加技术提升速度,尤其是在加载器这一环节,被称为just in time --JIT,即时编译技术,程序的速度因此得以提升。新版本的jdk中的java hotspot技术就采用了类似方法,代码每次被执行的时候都会被做一些优化,所以执行的越多,反而他的速度越快。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值