A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 魏-玉-彪 中级黑马   /  2012-8-31 07:28  /  3573 人查看  /  6 人回复  /   1 人收藏 转载请遵从CC协议 禁止商业使用本文

Java的垃圾回收机制的原理是什么?谁能介绍一下Java的垃圾回收机制的规则和执行时机?

6 个回复

倒序浏览
本帖最后由 马小龙 于 2012-8-31 12:50 编辑

首先要明确几点:
        第一:在垃圾回收器回收垃圾之前,我们先来了解一下Java分配对象的方式,Java的堆更像一个传送带,每分配一个新对象,它就往前移动一格。这意味着对象存储空间的分配速度相当快。Java的“堆指针”只是简单地移动到尚未分配的领域。也就是说,分配空间的时候,“堆指针”只管依次往前移动而不管后面的对象是否还要被释放掉。如果可用内存耗尽之前程序就退出就再好不过了,这样的话垃圾回收器压根就不会被激活。但是由于“堆指针”只管依次往前移动,那么你肯定会想,总有一  天内存会被耗尽,垃圾回收器就开始释放内存。这里有人肯定会问:怎么判断某个对象该被回收呢?答案就是当堆栈或静态存储区没有对这个对象的引用时,就表示程序(员)对这个对象没有兴趣了,它就应该被回收了。有两种方法来知道这个对象有没有被引用:第一种是遍历堆上的对象找引用;第二种是遍历堆栈或静态存储区的引用找对象。前者的实现叫做“引用计数法”,意思就是当有引用连接至对象时,引用计数加1,当引用离开作用域或被置为null时,引用计数减1,这种方法有个缺陷,如果对象之间存在循环引用,可能会出现“对象应该被回收,但引用计数却不为零”的情况。

        第二:Java采用的是后者,在这种方式下,Java虚拟机采用一种“自适应”的垃圾回收技术,如何处理找到的存活对象(也就是说不是垃圾),
        Java有两种方式:
                一种是“停止-复制”:理论上是先暂停程序的运行(所以它不属于后台回收模式),然后将所有存活的对象从当前堆复制到另一个堆,没有被复制的全是垃圾。当对象被复制到新堆上时,它们是一个挨着一个的,所以新堆保持紧凑排列(这也是为什么分配对象的时候“堆指针”只管依次往前移动)。然后就可以按前述方法简单、直接地分配内存了。这将导致大量内存复制行为,内存分配是以较大的“块”为单位的。有了块之后,垃圾回收器就可以不往堆里拷贝对象了,直接就可以往废弃的块里拷贝对象了。

                另一种是“标记-清扫”:它的思路同样是从堆栈和静态存储区出发,遍历所有的引用,进而找出所有存活的对象。每当它找到一个存活对象,就会给对象一个标 记。这个过程中不会回收任何对象。只有全部标记完成时,没有标记的对象将被释放,不会发生任何复制工作,所以剩下的堆空间是不连续的,然后垃圾回收器 重新整理剩余的对象,使它们是连续排列的。

                当垃圾回收器第一次启动时,它执行的是“停止-复制”,因为这个时刻内存有太多的垃圾。然后Java虚拟机会进行监视,如果所有对象都很稳定,垃圾回收器的效率降低的话,就切换到“标记-清扫”方式;同样,Java虚拟机会跟踪“标记-清扫”效果,要是堆空间出现很多碎片,就会切换到“停止-复制”方式。这就是  所谓的“自适应”技术。其实仔细想一下,“停止-复制”和“标记-清扫”无非就是:“在大量的垃圾中找干净的东西和在大量干净的东西里找垃圾”。不同的                  环境用不同的方式,这样做完全是为了提高效率,要知道,无论哪种方式,Java都会先暂停程序的运行,所以,垃圾回收器的效率其实是很低的。!

                最后要说在网络上查询了不少细节,对自己也是一个总结帮助,希望对你有用.

点评

好  发表于 2012-8-31 18:25

评分

参与人数 2技术分 +1 黑马币 +2 收起 理由
魏-玉-彪 + 2 很给力!
包晗 + 1

查看全部评分

回复 使用道具 举报
Java的堆是一个运行时数据区,类的实例(对象)从中分配空间。
Java虚拟机(JVM)的堆中储存着正在运行的应用程序所建立的所有对象,这些对象通过new、newarray、anewarray和multianewarray等指令建立,但是它们不需要程序代码来显式地释放。
垃圾回收是一种动态存储管理技术,它自动地释放不再被程序引用的对象,按照特定的垃圾收集算法来实现资源自动回收的功能。
在Java中,当没有对象引用指向原先分配给某个对象的内存时,该内存便成为垃圾。JVM的一个系统级线程会自动释放该内存块。垃圾收集意味着程序不再需要的对象是"无用信息",这些信息将被丢弃。当一个对象不再被引用的时候,内存回收它占领的空间,以便空间被后来的新对象使用。事实上,除了释放没用的对象,垃圾收集也可以清除内存记录碎片。由于创建对象和垃圾收集器释放丢弃对象所占的内存空间,内存会出现碎片。碎片是分配给对象的内存块之间的空闲内存洞。碎片整理将所占用的堆内存移到堆的一端,JVM将整理出的内存分配给新的对象。
Java语言规范没有明确地说明JVM使用哪种垃圾回收算法,但是任何一种垃圾收集算法一般要做2件基本的事情:
(1)发现无用信息对象;(2)回收被无用对象占用的内存空间,使该空间可被程序再次使用
1、 引用计数法(Reference Counting Collector)
2、tracing算法(Tracing Collector)
3、compacting算法(Compacting Collector)
4、copying算法(Coping Collector)
5、generation算法(Generational Collector)
6、adaptive算法(Adaptive Collector)

评分

参与人数 2技术分 +1 黑马币 +2 收起 理由
魏-玉-彪 + 2 很给力!
包晗 + 1

查看全部评分

回复 使用道具 举报
简单概括的说,垃圾回收机制:
1. 跟踪并监控每个Java对象,当某个对象处于不可达状态时,回收该对象所占用的内存;
2. 清理内存分配,回收过程中产生的内存碎片。
JVM判断某个对象是否可以回收的唯一标准是:是否还有其他引用指向该对象,如果存在引用指向该对象,垃圾回收机制就不会回收该对象,否则,垃圾回收机制就会尝试回收它。
实际上,垃圾回收机制不可能实时检测到每个java对象的状态,因为当一个对象失去引用后,它不会被立即回收,只有等垃圾回收运行时才会被回收。

评分

参与人数 2技术分 +1 黑马币 +2 收起 理由
魏-玉-彪 + 2 很给力!
包晗 + 1

查看全部评分

回复 使用道具 举报
黄珊珊 发表于 2012-8-31 13:57
简单概括的说,垃圾回收机制:
1. 跟踪并监控每个Java对象,当某个对象处于不可达状态时,回收该对象所占用 ...

看了楼上 的技术分得的 多好 “只看远观而不可亵玩焉”
回复 使用道具 举报
谢谢各位大侠,请问Java的垃圾回收时是否占用内存?占用多少?虚拟机是怎样保证在内存耗尽之前启动Java的垃圾回收机制的?
回复 使用道具 举报
原问题已解决
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马