Java的垃圾回收以及常用的垃圾回收算法

Java内存管理主要涉及三个部分:堆(Java代码可及的Java堆和JVM自身使用的方法区)、栈(服务Java方法的虚拟机栈和服务Native方法的本地方法栈)和保证程序在多线程环境下能够连续执行的程序计数器。

Java堆是进行垃圾回收的主要区域,故其也称为GC堆;而方法区的垃圾回收主要针对的是新生代和中生代。总的来说,堆(包括Java堆和方法区)是垃圾回收的主要对象,特别是Java堆。

判断对象是否需要回收?(也就是对象存活判断):

这里有两种算法:

1、引用计数

每个对象有一个引用计数属性,新增一个引用时计数加1,引用释放时计数减1,计数为0时可以回收。此方法虽然简单,但无法解决对象相互循环引用的问题。

2、可达性分析

从GC Roots开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的。在Java中,GC Roots包括:

  • 虚拟机栈中引用的对象
  • 方法区中类静态属性实体引用的对象
  • 方法区中常量引用的对象
  • 本地方法栈中JNI引用的对象

垃圾回收:

这里有三种算法:

1、标记清除算法

见名知意,两步:

第一步:标记出所有需要被回收的对象

第二步:对标记的对象进行统一清除,清空对象所占的内存区域

缺点:

第一:执行效率不可控

第二:产生了许多内存碎片

2、标记复制算法

这个算法是针对标记清除算法执行效率与内存碎片的缺点,提出的一种改进算法。

就是将内存分为大小相同的两个区域,运行区域和预留区域,所有创建的新对象都分配到运行区域,当运行区域不够时,将运行区域中存活对象全部复制到预留区域,然后再清空整个运行区域内存。

这个能够很好的兼顾了执行效率与内存碎片的问题。

但是也存在缺点:预留一半的内存区域未免有些浪费了。

3、标记整理算法

于是又产生了一种算法,标记整理算法,其标记阶段与其他算法一样,但是在整理阶段,算法是将存活的对象向内存空间一端移动,然后将存活对象边界以外的空间全部清空。

这种看上去挺美好的,其中也有不足,比如说当垃圾对象少的时候,要移动大量的存活对象才能获取少量的内存空间。

总之,不同的垃圾回收算法都有各自的优缺点。

猜你喜欢

转载自blog.csdn.net/zdj_Develop/article/details/121616770