JAVA的垃圾回收原理

JAVA的垃圾回收原理

今天读到java的垃圾回收原理,觉得循序渐进的理解过程很有意思,就记录下来以备后用。主要分以下几个环节理解:

  • 最便于理解的基本原理的讲解
  • 提高效率的改进方法
  • 降低开销的附加方法
  • 进一步降低开销的自适应方法

最便于理解的基本原理的讲解

垃圾回收是对堆内不再被引用的对象所占内存空间的回收操作。所以判断是不是垃圾,就是判断对象是否还有引用。

那么如果给每个对象准备一个计数器,来记录其上的引用个数,每增加一个引用,计数器加1,每减少一个引用,计数器减1(减到0为止),在回收的时候,遍历所有对象,对计数器为0的对象的内存进行回收即可。

这样非常便于理解,但是遍历堆中的所有对象效率很低,另外还有个致命的问题,如果出现对象间的循环引用,当外部对他们的引用消失时,他们就应该被回收,可是他们的计数器却都不为0,这就出现了无法回收的内存,容易导致内存泄露。

提高效率的改进方法

从堆栈中的一个引用出发,找到它引用的对象,再找到这个对象包含的引用,反复进行,直到遍历完所有引用,就能找到所有不是垃圾的对象,把这些对象复制到新堆中,同时更新他们的引用指向新堆的内存地址,最后再把旧的堆整个回收,这样就不会出现循环引用无法回收的问题,而且复制后堆中的地址是连续的,不会出现碎片。

这种方法叫做“停止-复制 ”,回收时程序会暂停。停止-复制 的效率提高很多,但它的最大开销是复制的过程。

降低开销的附加方法

内存分配以块为单位,有的对象很大,单个对象就会占用一个块,如果对这样的大对象进行复制,开销大且并没有实际意义。

为了避免对块的无意义的复制,给每个块做个标记,标记它是否在用,遍历引用时,如果发现的是小对象,则复制到新块,回收结束后对新块进行整理。如果发现的是大对象,则对块做标记,不需要复制,这样就减少了复制的开销。

进一步降低开销的自适应方法

如果内存里并没有多少垃圾,进行一次停止-复制 就会白白消耗很多资源。为了避免在没有垃圾时的停止-复制,还有种方法叫做“标记-清扫 ”。在遍历引用发现对象时,给对象设置一个标记,当遍历结束时,没有任何标记的对象即为垃圾,会被全部清理。

这种清理不会复制,因此清理后的区域会出现碎片,只能在垃圾很少甚至没有时使用,所以它应该和停止-复制 结合起来使用,当对象都比较稳定时,进行标记-清扫 ,当发现大量碎片时,进行停止-复制 ,这就是自适应 技术。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值