文档章节

java GC垃圾回收

wangtx
 wangtx
发布于 2016/04/25 00:09
字数 1597
阅读 81
收藏 3

垃圾回收机制

一、引用计数

特点:

简单,速度慢

原理:

每个对象都含有一个引用计数器,当有引用连接值对象是,引用计数加1.当引用离开作用域或被置为null时,引用计数减1.虽然管理引用计数的开销不大,但这项开销在整个程序生命周期中将持续发生。垃圾回收器会在含有全部对象的遍历表上遍历,当发现某个对象的引用计数为0时,就释放其占用的空间。但是,引用计数模式经常会在计数值变为0时立即释放对象。这种方法还有个缺陷,如果对象之间存在循环引用,可能会出现对象应该被回收,但引用计数却不为0的情况。对垃圾回收器而言,定位这样的的交互自引用的对象组所需的工作量极大。

评价:

这种方式常用来说明垃圾收集的工作方式,但似乎从未被应用于java虚拟机实现中。

二、遍历所有的引用

思想:

对任何活的对象,一定能最终追溯到器存活在堆栈或静态存储区之中的引用。这个引用链条可能会产国数个对象层次,由此,如果从堆栈和静态存储区开始,遍历所有的的引用,就能找到所有活的对象。这种方式解决了交互自引用的对象组的问题。

这种方式下java虚拟机将此采用一种自适应的垃圾回收技术。至于如何处理找到的存活对象,取决于不同的实现。

  1. 停止-复制

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

    评价:

    这种所谓的复制式回收器,效率会降低,两个原因。

    首先,得有两个堆,然后在两个分离的堆之间来回倒腾,从而得维护比实际需要多一倍的空间。某些java虚拟机对此问题的处理方式是,按需从堆中分配几块较大的内存,复制动作发生在这些大块内存之间。

    第二个问题在于复制,程序进入稳定状态之后,可能只会产生少量垃圾,甚至没有垃圾。尽管如此,复制式回收器仍然会将所有内存自一处复制到另一处,这很浪费。为了避免这种情形,一些java虚拟机会进行检查:要是没有新垃圾产生,就会转换到另一种工作模式(即:自适应)。这种模式成为标记-清扫,sun公司早期的java虚拟机使用了这种技术。对一般用途而言,标记-清扫方式速度相当慢,但是当你知道只会产生少量垃圾甚至不会产生垃圾时,它的速度就很快了。

  2. 标记-清扫

    思路同样是从堆栈和静态存储区出发,遍历所有的引用,进而找出所有存活的对象。每当它找到一个存活的对象,它就会给对象设一个标记,这个过程中不会回收任何对象。只有全部标记工作完成的时候,清理动作才会开始。在清理过程中,没有标记的对象将被释放,不会发生任何复制动作。所以剩下的空间是不连续的,垃圾回收器要是希望得到连续空间的话,就得重新整理剩下的对象。

    三、综述

    “停止-复制”的意思是这种垃圾回收动作不是在后台进行的;相反,垃圾回收动作发生的同时,程序将会被暂停。在sun公司的文档中会发现,许多参考文献将垃圾回收视为低优先级的后台进程,但事实上垃圾回收器在sun公司早期版本的java虚拟机中并非以这种方式实现的。当可用内存数量较低时,sun版本的垃圾回收器会暂停运行程序,同样,“标记-清扫”工作也必须在程序暂停的情况下才能进行。

    如前文所述,在这里所讨论的java虚拟机中,内存分配以较大的“块”为单位。如果对象较大,它会占用单独的块。严格来说,“停止-复制”要求在释放旧有对象之前,必须先把所有存活对象从旧堆复制到新堆,这将导致大量内存复制行为。有了块之后,垃圾回收器在回收的时候就可以往废弃的块里拷贝对象了。每个块都用相应的“代数”来记录他是否还存活。通常,如果块在某处被引用,其“代数”会增加;垃圾回收器将对上次回收动作之后新分配的块进行整理。这对处理大量短命的临时对象很有帮助。垃圾回收器会定期进行完整的清理动作——大型对象仍然不会被复制(只是其代数会增加),内含小型对象的块则被复制并整理。java虚拟机会进行监视,如果所有对象都很稳定,垃圾回收器的效率降低的话,就切换到“标记-清扫”方式;同样java虚拟机会跟踪“标记-清扫”的效果,要是对空间出现很多碎片,就会切换回“停止-复制”方式。这就是“自适应”技术。(自适应的、分代的、停止-复制、标记-清扫式垃圾回收器)

    四、其他文章

    看了一篇讲解详细的文章,与上面写的机制能够对应起来,可以看一下,能够清楚常用的jvm的详细的各种垃圾回收方式。http://www.cnblogs.com/zhguang/p/3257367.html#commentform

© 著作权归作者所有

wangtx
粉丝 7
博文 41
码字总数 27236
作品 0
济南
程序员
私信 提问
Java GC系列:Java垃圾回收详解

Java的内存分配与回收全部由JVM垃圾回收进程自动完成。与C语言不同,Java开发者不需要自己编写代码实现垃圾回收。这是Java深受大家欢迎的众多特性之一,能够帮助程序员更好地编写Java程序。 ...

满风
2015/04/10
617
0
[Java性能剖析]Sun JVM内存管理和垃圾回收

内存管理和垃圾回收是JVM非常关键的点,对Java性能的剖析而言,了解内存管理和垃圾回收的基本策略非常重要。本篇对Sun JVM 6.0的内存管理和垃圾回收做大概的描述。 1.内存管理 在程序运行过程...

会爬墙的猫
2011/07/22
227
0
JVM系列第10讲:垃圾回收的几种类型

我们经常会听到许多垃圾回收的术语,例如:Minor GC、Major GC、Young GC、Old GC、Full GC、Stop-The-World 等。但这些 GC 术语到底指的是什么,它们之间的区别到底是什么?今天我们就来详细...

陈树义
2018/12/10
0
0
《成神之路-基础篇》JVM——垃圾回收(已完结)

Java内存模型,Java内存管理,Java堆和栈,垃圾回收 本文是[《成神之路系列文章》][1]的第一篇,主要是关于JVM的一些介绍。 持续更新中 Java之美[从菜鸟到高手演变]之JVM内存管理及垃圾回收 ...

2018/05/05
0
0
JVM系列第8讲:JVM 垃圾回收机制

在第 6 讲中我们说到 Java 虚拟机的内存结构,提到了这部分的规范其实是由《Java 虚拟机规范》指定的,每个 Java 虚拟机可能都有不同的实现。其实涉及到 Java 虚拟机的内存,就不得不谈到 Ja...

陈树义
2018/11/21
0
0

没有更多内容

加载失败,请刷新页面

加载更多

006-Docker中导出单个或多个tar包

docker中导出单个镜像和多个镜像的tar包 docker save [images] > [name.tar] docker save [images] [images] > [name.tar]...

伟大源于勇敢的开始
今天
6
0
Kotlin基础语法学习

安装好安卓studio,以及插件支持Kotlin 就可以在创建项目的时候选择 Kotlin语言了。 https://www.jianshu.com/p/4ab13691d681 参考手册: https://www.runoob.com/kotlin/otlin-android-setu...

T型人才追梦者
今天
4
0
java实现简单计算器

1.概述 之前作者写过一篇文章,也是关于计算器的,用的是C++与Qt,链接在这里 这次用java的swing写的(这差距好像有点大,好吧是qt太强了). 先上图: 2.UI 总体布局使用流布局. (1)文本框 文本框就...

Blueeeeeee
今天
4
0
纯CSS实现DIV悬浮(固定位置)

纯CSS实现的DIV悬浮效果(固定位置),兼容常用的浏览器:IE8、360、FireFox、Chrome、Safari、Opera、傲游、搜狗、世界之窗等。效果如下: 实现代码: <!DOCTYPE html> <html> <head> <meta ...

独钓渔
今天
6
0
OSChina 周二乱弹 —— 给我来个女菩萨

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @这次装个文艺青年吧 :#今日歌曲推荐#分享XXXTENTACION/Travis Barker的单曲《Pain = BESTFRIEND》: 《Pain = BESTFRIEND》- XXXTENTACION/...

小小编辑
今天
12
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部