黑马程序员技术交流社区

标题: 垃圾回收机制,如何优化程序? [打印本页]

作者: 何万县    时间: 2012-4-19 16:32
标题: 垃圾回收机制,如何优化程序?
谁能告诉我,java垃圾回收机制,如何优化程序,谢谢各位!
作者: 乞文超    时间: 2012-4-19 16:34
当一个对象失去引用或者离开了作用域后,就成为垃圾而被Java运行环境自动清除,清除垃圾就是清除这些对象。
        Java垃圾回收机制的特点是:
垃圾回收机制自动运行。系统提供一个低优先级的线程来跟踪内存的分配情况。如果发现某个内存单元不再使用,就清除它。
何时清除垃圾是不可预期的。
垃圾回收机制随JVM的不同而不同。
       
        Java的垃圾搜索器为内存管理器提供一种自动解决方案。缺点是不能完全控制它什么时候执行以及什么时候不执行。
        当垃圾搜集器运行时,其目的是查找和删除不能被访问的对象。
        垃圾搜集器受JVM控制,JVM决定什么时候运行垃圾搜集器。从Java程序内可以请求JVM运行垃圾搜集器,但是,在任何情况下都无法保证JVM会答应你的请求。JVM通常会在它感到内存减少时运行垃圾搜集器。
        垃圾收集器运行时,当它发现一个对象不能被任何活线程访问时,它将认为该对象符合删除条件,它可能在某时删除该对象。
        垃圾收集器不能保证有足够的内存,它只能保证可以使用的内存将尽可能被有效的管理。
        使对象符合垃圾搜集器搜索条件的情况有:出现空引用、重新为引用变量赋值、隔离引用。

        强制执行垃圾搜集:
        Runtime对象为直接与虚拟机通信提供一种机制。System类可以调用与其相同的方法。
        请求垃圾收集器的最简单的方法是:System.gc();

作者: 张超超    时间: 2012-4-19 16:56
java垃圾回收就是 系统自动把heap(堆)中没有引用指向的对象定期删除
这个是定期自动调用,一般不用去考虑回收的时间点,另外,如果heap中对象比内存多,这时是会报错的。
JAVA垃圾回收机制另一个特点是,进行垃圾回收的线程是一种低优先级的线程,在一个Java程序的生命周期中,它只有在内存空闲的时候才有机会运行。

垃圾回收线程遵循以下两个特性。
1.  自动性。Java技术提供了一个系统级的线程,即垃圾收集器线程,来跟踪每一块分配出去的内存空间,当Java 虚拟机处于空闲循环时,垃圾收集器线程会自动检查每一块分配出去的内存空间,然后自动回收每一块可以回收的无用的内存块。
2.  不可预期性。一个对象成为了垃圾,但是你不能断言,该对象在这行以后就立刻被清除,甚至有可能当程序结束后,该对象仍然占用内存。像Windows这样的软件常常会出现内存不足的情况,JAVA程序很少出现就是因为可以自动回收内存。然而,因为JAVA也不能保证及时地清除无用的对象,所以JAVA程序也会出现内存不足的情况,只是这种情况很少出现。垃圾收集线程在一个Java程序中的执行是自动的,不能强制执行,即使程序员能明确地判断出有一块内存已经无用了,是应该回收的,程序员也不能强制垃圾收集器回收该内存块。程序员唯一能做的就是通过调用System.gc 方法来"建议"执行垃圾收集器,但其是否可以执行,什么时候执行却都是不可知的。

希望对你有帮助
作者: liqian    时间: 2012-4-19 17:17

1.JVM中有一个垃圾回收器.当某对象不再被任何变量引用时,其内存才可能被回收;回收之前会调用finalize()方法,该方法有可能取消回收操作。
2.过程:
程序中有变量引用对象,回收器什么都不做;
程序中没有变量引用对象,垃圾回收器会准备释放对象占用的内存,释放之前,调用finalize()方法,该方法有可能取消回收操作。
JVM执行完finalize(),垃圾回收器回收对象的内存
3.两种常用的方法是引用计数和对象引用遍历
引用计数:对特定的所有引用数,也就是说,当应用程序创建引用以及引用超出范围时,jvm必须适当的增减引用数,当某对象的引用数为0时,便可以进行垃圾收集。   
对象引用遍历:对象引用遍历从一组对象开始,沿着整个对象图赏的每条链接,递归确定可以达到的对象,如果某对象不能从这些根对象 的一个到达,则他将作为垃圾收集,在对象遍历阶段,gc必须记住哪些对象可以到达,以便删除不可以达到的对象,这个动作称为标记对象。
作者: 陈坚    时间: 2012-4-19 19:08
  JVM内存分四种:
1、栈区(stacksegment)—由编译器自动分配释放,存放函数的参数值,局部变量的值等,具体方法执行结束之后,系统自动释放JVM内存资源
2、堆区(heapsegment)—一般由程序员分配释放,存放由new创建的对象和数组,jvm不定时查看这个对象,如果没有引用指向这个对象就回收
3、静态区(datasegment)—存放全局变量,静态变量和字符串常量,不释放
4、代码区(codesegment)—存放程序中方法的二进制代码,而且是多个对象共享一个代码空间区域

一些常用的垃圾收集器
(1)标记-清除收集器
这种收集器首先遍历对象图并标记可到达的对象,然后扫描堆栈以寻找未标记对象并释放它们的内存。这种收集器一般使用单线程工作并停止其他操作。并且,由于它只是清除了那些未标记的对象,而并没有对标记对象进行压缩,导致会产生大量内存碎片,从而浪费内存。
(2)标记-压缩收集器
有时也叫标记-清除-压缩收集器,与标记-清除收集器有相同的标记阶段。在第二阶段,则把标记对象复制到堆栈的新域中以便压缩堆栈。这种收集器也停止其他操作。
(3)复制收集器
这种收集器将堆栈分为两个域,常称为半空间。每次仅使用一半的空间,JVM生成的新对象则放在另一半空间中。GC运行时,它把可到达对象复制到另一半空间,从而压缩了堆栈。这种方法适用于短生存期的对象,持续复制长生存期的对象则导致效率降低。并且对于指定大小堆来说,需要两倍大小的内存,因为任何时候都只使用其中的一半。
(4) 增量收集器
增量收集器把堆栈分为多个域,每次仅从一个域收集垃圾,也可理解为把堆栈分成一小块一小块,每次仅对某一个块进行垃圾收集。这会造成较小的应用程序中断时间,使得用户一般不能觉察到垃圾收集器正在工作。
(5)分代收集器
复制收集器的缺点是:每次收集时,所有的标记对象都要被拷贝,从而导致一些生命周期很长的对象被来回拷贝多次,消耗大量的时间。而分代收集器则可解决这个问题,分代收集器把堆栈分为两个或多个域,用以存放不同寿命的对象。JVM生成的新对象一般放在其中的某个域中。过一段时间,继续存在的对象(非短命对象)将获得使用期并转入更长寿命的域中。分代收集器对不同的域使用不同的算法以优化性能。







欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2