Java中的垃圾回收机制(Java编程思想摘要)

Java中的垃圾回收机制(Java编程思想摘要)

 垃圾回收器负责回收无用对象占据的内存资源(前提是这个对象是new出来的),假设对象并非通过使用new获得了内存,那么这块内存需要手动释放掉,Java允许在类中定义一个名为finalize()的方法。
它的工作原理:
 一旦垃圾回收器准备释放对象所占用的空间,会首先调用finalize方法,并且在下一次垃圾回收动作发生时,才会真正回收对象占用的内存。所以只有在垃圾回收的时候才会将内存回收。
 但是,只有程序在濒临存储空间用完的时候,才会进行垃圾回收,如果一直有充足的空间,那么我们的finalize就永不得不到调用,也就是说我们想在finalize中释放的内存也就一直无法得到释放
 引用计数是一种简单但速度很慢的垃圾回收技术。每个对象都含有一个引用计数器,当有引用连接至对象时,引用计数加1。当引用离开作用域或被置为null时,引用计数减1。虽然管理引用计数的开销不大,但是这项开销在整个程序生命周期中将持续发生。垃圾回收器会在含有全部对象的列表上遍历,当发现某个对象的引用计数为0时,就释放其占有的空间。这种方法有个缺陷,如果对象之间存在循环引用,就会出现循环引用的对象所占用的空间永远无法被释放的情况,对于垃圾回收器来说,定位这样的交互引用的对象组所需的工作量极大。这种工作方式没有被应用于任何一种java虚拟机中。
 垃圾回收器并非基于引用计数技术。他们依据的思想是:对任何”活“的对象,一定能最终追溯到其存活在堆栈或静态存储区中的引用。由此,如果从堆栈和静态存储区开始。遍历所有的引用,就能找到所有”活“的对象。然后是此对象包含的所有引用,如此反复进行,直到”堆栈和静态存储区的引用“所形成的网络全部被访问为止。

  •  stop-and-copy方式
     暂停程序运行,将所有存活的对象从当前堆复制到另一个堆,没有被复制的全部都是垃圾。当对象被复制到新堆时,它们是一个挨着一个的,所以新堆保持紧凑排列。当把对象从一处搬到另一处时,所有指向它的那些引用都必须修正。位于堆或静态存储区的引用可以直接被修正,但可能还有其他指向这些对象的引用,它们在遍历的过程中才能被找到。
      效率降低的两个原因:
        1.需要比实际多一倍的空间
        2.如果只有少量的垃圾,依然需要整块复制内存,造成浪费。为了避免这种情况。一些java虚拟机会进行检查,要是没有新垃圾产生,就会转换到另一种工作模式,mark-and-sweep。

  •  mark-and-sweep:
     遍历所有应用,找出所有存活对象,进行标记,当全部标记工作完成,开始清理,没有标记的对象将被释放,不会发生任何复制动作。所以剩下的堆空间都是不连续的,垃圾回收器如果希望得到连续的空间的话,就得重新整理剩下的对象。‘
    内存分配以较大的”块“为单位。如果对象较大,它会占用单独的块。 stop-and-copy要求在释放旧对象之前,必须先把所有存活对象从旧堆复制到新堆,这将导致大量内存复制行为。有了块之后,垃圾回收器在回收的时候就可以往废弃的块里拷贝对象了。每个块都用相应的代数来记录它是否还存活。通常,如果块在某处被引用,其代数会增加。垃圾回收期会定期进行完整的清理动作,大型对象仍然不会被复制(代数会增加),内含小型对象的那些块则被复制并整理。Java虚拟机会进行监视,如果所有对象都很稳定,垃圾回收器效率降低的话,就切换到mark-and-sweep方式。同样,Java虚拟机会跟踪效果,要是堆空间出现很多碎片,就会切换回stop-and-copy方式。

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值