美文网首页
JAVA对象的回收与垃圾回收器的工作方式

JAVA对象的回收与垃圾回收器的工作方式

作者: HopeMan | 来源:发表于2018-07-15 22:43 被阅读6次

    1:对象的回收前期工作

    finalize()方法的调用:

    当一个对象不再使用时会被java虚拟机销毁,并回收其所占内存。java中并没有像c++中的析构函数,当调用对象的delete()方法时,在析构函数中做一些资源释放的工作。

    1)在java中,当我们调用System.gc()时,Java垃圾回收并不会直接执行或者根本不会执行,这主要取决于java虚拟机此时对程序运行状态的一个评测。

    2)当一个对象被垃圾回收器回收前,会首先会调用其finalize()方法,在这个方法中我们可以做一些与内存无关的内存回收工作,例如对文件的访问、socket的连接断开、jni资源的释放,最后还要调用super.finalize()。

    2:垃圾回收器的工作方式:“标记-清扫”和“停止-复制”

    1)java中所有对象都是在堆内存中创建的

    2)堆内存的分配,由于java垃圾回收器的介入,使得对象的内存分配效率提高很多

    标记-清扫

    在进行一次gc的过程中,java虚拟机会扫描堆内存和静态存储区的所有对象,并对其进行“存活”状态标记,扫描完成后(扫描过程中不清理对象,扫描完成后才开始清理),将没有被标记为“存活”状态的对象进行销毁(不会发生复制“存活”对象到另一个堆区域的动作),也就是所谓GC ROOT无法到达的对象,此时会存在很多不连续的堆空间,如果垃圾回收器希望得到连续的空间,就需要重新整理“存活对象”。此过程进行前,程序需要暂停。

    停止-复制

    垃圾清理过程中,死对象清理的同时,会将“活对象”复制到另一个堆中,以使所有“活对象”拥有连续的内存空间,这样为新对象的内存分配提高了效率,但也带来了问题。第一需要两个堆内存区域,“活对象”需要在这两个区域进行复制,这样内存开销太大;第二由于对象指向的内存发生了变化,那么此时就需要对对象进行地址修改。此过程进行前,程序需要暂停。

    随着java虚拟机的新技术出现,对“死对象”和“活对象”内存有了改善。此时虚拟机会按块分配内存,当一个对象被销毁后,此块就会被标记为废弃,此时就可以直接往废弃块中拷贝对象,这样就不必分配两个单独的堆区域,同时垃圾回收器也会在回收之后对内存进行整理。

    总结

    针对以上“标记-清扫”和“停止-复制”,java虚拟机采用一种被称为“自适应”的方式工作。当内存充足,gc频率低,程序处于一种比较稳定的状态时,此时就会采用“标记-清扫”模式。但是在长期的gc之后,如果碎片化比较严重(因为“标记-清理”模式,只是释放"死对象"堆内存,并未对区域进行整理),此时就会切换到“停止-复制”模式。

    相关文章

      网友评论

          本文标题:JAVA对象的回收与垃圾回收器的工作方式

          本文链接:https://www.haomeiwen.com/subject/tzsmpftx.html