关于JVM 的垃圾回收机制,我们一般都没过多深入,因为JAVA 和 C++ 的一个很大区别就是,JAVA 帮我们做了垃圾回收,而不用像C++ 那么样手动进行回收,当然任何自动的东西都存在一定弊端,比如机器人,即使自动程度很高,但是在处理某些感情问题上,肯定处理上就会有遗漏,开个玩笑啦,下面我们先来了解一下JVM 的垃圾回收是怎么回事。
一、如何判断对象已经死亡
JVM 会回收那些不在使用的对象,或者说是已经死亡的对象,从而达到节省空间的目的,那么我们肯定的判断哪些对象已经死了,不在使用呢?
1 引用计数算法:
这算法原理很简单,就是当我们的对象没引用的时候,有一个计数器,比如count,就会count ++,同理,如果被应用的对象设为null,那么count --,直到 count = 0的为止。当JVM 进行回收的时候,那么他会找到这些count = 0 的对象,默认没有被使用,就进行回收了。
这个算法,理论上是挺好的,但是当对象相互引用的时候就无法进行了,举个例子:比如A 类,里面有个B类的引用 b,同时B类里面有个A类的引用a,当我们同时A a= new A(),B b = new B();这时候是一个强引用,都会count ++,当我们让里面的引用a.b =b,b.a=a;的时候就是第二次引用,count 都变成了2,如果这时让
a =null,b =null,count -- ,当我们回收的时候发现count = 1;JVM 就不会回收了,那么就会浪费内存,这也是引用计数算法的主要劣势,这里也顺便分析下这种算法:
1. 需要单独的字段存储计数器,增加了存储空间的开销;
2. 每次赋值都需要更新计数器,增加了时间开销;
3. 垃圾对象便于辨识,只要计数器为0,就可作为垃圾回收;
4. 及时回收垃圾,没有延迟性;
5. 不能解决循环引用的问题;
2 可达性分析算法
这种算法可以对象循环引用的问题,基本原理是:通过一个叫“GC ROOT”根对象作为起点,然后向下节点搜索,搜索路径叫引用链,也就是我们常说的引用,当我们从ROOT 找不到任何一条路径相连的对象的情况下,就可以判定可以回收了,相当于这对象找不到家的感觉,这里引用JVM的图:
2 .1 GC ROOT 回收对象的范围包括:
a. 虚拟机栈(栈帧中的本地变量表)中引用的对象
b. 方法区中类静态属性引用的对象
c. 方法区中常量引用的对象
d. 本地方法栈中JNI(native方法)引用的对象
关于一些堆栈 方法区的分布作用,以后再讲,可以先参考:
http://www.360doc.com/content/11/0504/12/3903749_114271703.shtml
虽然有可达性分析算法来判定对对象状态,但这并不是对象是否被回收的条件,对象回收的条件远远比这个复杂,比如无法通过ROOT找到的对象,也不一定会回收,会进入一个死缓的阶段,那些无法通过根节点 引用链找到的对象,会被第一次标记,并进行一次筛选,筛选条件是此对象是否有必要执行finalize()方法,当对象没有覆盖finalize()方法,或者finalize() 方法已经被虚拟机调用过,虚拟机都视为“没必要执行”。
如果该对象被判定为有必要执行finalize(),那么对象会被放置在一个F-Queue 的队列中,并由一个优先级较低的Finalizer 线程去执行,这里的执行是 JVM 会触发这个方法,但并不保证等待他运行结束,因为finalize() 方法执行慢,或者死循环,会影响该队列其他元素执行。
执行finalize() 方法就会进行第二次标记,然后等待JVM 进行回收了,而在finalize() 方法执行的同时,可以对对象进行“拯救”,也就是说在执行方法内部,再次对对象进行引用,那么对象就复活了,看代码:
package com; import java.lang.reflect.Method; import org.springframework.cglib.proxy.MethodInterceptor; import org.springframework.cglib.proxy.MethodProxy; public class FinalizeGC{ public static FinalizeGC save_gc = null; public static void main(String[] args) throws InterruptedException { save_gc = new FinalizeGC(); // 断掉引用链 save_gc = null; // 调用finalize 回收,里面进行了 拯救 行动 System.gc(); // finalize 优先级比较低,暂停0.5秒等待他执行 Thread.sleep(500); System.out.println("该对象状态是--->"+save_gc); // 这里代码同上,但是已经拯救无效 save_gc = null; System.gc(); Thread.sleep(500); System.out.println("该对象状态是--->"+save_gc); } // 重写该方法 @Override protected void finalize() throws Throwable { super.finalize(); System.out.println("正在执行 finalize 方法"); // 从新引用 FinalizeGC.save_gc = this; } } 结果: 正在执行 finalize 方法 该对象状态是--->com.FinalizeGC@c17164 该对象状态是--->null
可以看出,finalize 在GC的时候已经执行了,并且对象已经被拯救了,但是发现只被执行了一次,也就只能被拯救一次,因此有一个有值,有一个是null.这里可以看出JVM 对对象的finalize()只会被执行一次,这里仅仅做了解,不建议重写该方法,因为这样会干扰对象的回收调用机制,而且运行代价很高。
除了上述那些对象以外,还有一些废弃常量的回收,比如:有一个一个字符串"ABC" 已经进入常量池中,但是当前系统没有任何地方引用该对象,该常量就会被清除常量池。
同时还有一些废弃的类,或者无用的类也会被回收,这里一些判定条件有:
a.该类所有的实例都已经被回收,也就是Java堆中不存在该类的任何实例
b.加载该类的ClassLoader 已经被回收
c.该类的java.lang.Class 对象在没有任何地方呗引用,无法在任何地方通过反射访问该类的方法。
小结:
1.这里仅描述了一些JAVA 对象是否可以回收的一些判定方法和条件
2.关于还有垃圾收集的一些算法以及垃圾回收器,这些才是描述JVM 如何整理这些分布在内存中的过期对象,如何进行批量的手机 删除工作的,这个以后再解释吧。
相关推荐
JVM垃圾回收机制通过两种主要算法来确定对象是否成为垃圾,即“可达性分析算法”和“引用计数法”。 - 可达性分析算法:这种方法通过确定对象的引用链来判断对象是否可达。GC根对象包括虚拟机栈中引用的对象、方法...
总结来说,理解JVM的内存分配策略和垃圾回收机制对于优化Java应用的性能至关重要。开发者需要根据应用的特性调整JVM参数,确保内存的有效利用,减少不必要的垃圾收集开销,从而提高系统的响应速度和稳定性。
#### 一、对象回收判定方法 在Java虚拟机中,判断一个对象是否可以被回收通常有两种方法:**引用计数法**和**可达性分析法**。 ##### 引用计数法 引用计数法是一种较为简单的对象回收策略,它的基本思想是在对象中...
Java垃圾回收机制是Java虚拟机(JVM)中的一种机制,用于释放垃圾占用的空间,以便提高系统性能和避免内存泄露。在Java中,垃圾回收机制主要解决两个问题:如何确定某个对象是“垃圾”?采用什么样的策略来进行回收...
Java语法简洁,面向对象,具有垃圾回收机制,以及强大的异常处理和多线程支持。 2. Java的开发流程: Java程序的开发通常包括编写源代码、编译、打包和运行四个步骤。源代码写在.java文件中,通过javac编译器编译成...
其次,垃圾回收机制中,何时回收是根据对象的存活状态来决定的。JVM采用可达性分析算法来判断对象是否存活。该算法通过一系列被称为GC Roots的对象作为起点,向下搜索,如果一个对象到GC Roots没有任何引用链相连,...
Java虚拟机(JVM)作为Java程序运行的基础,其内存管理、垃圾回收机制及性能优化是面试中的热门话题。本文将全面探讨这些核心知识点,并提供相关面试题目的解答。 首先,JVM内存主要分为五个区域:堆区、栈区、方法...
本文主要探讨了JVM的内存区域、线程私有部分、内存溢出异常、垃圾回收机制及其重要性。 首先,JVM内存区域可以分为五个主要部分: 1. **程序计数器**:这是一个线程私有的内存区域,用于存储当前线程执行的字节码...
本文将对 JVM 的内存区域、Java 内存模型(JMM)、垃圾回收机制、JVM 参数配置等知识点进行详细的解释和总结。 JVM 的内存区域 JVM 的内存区域包括堆、元空间、Java 虚拟机栈、本地方法栈、程序计数器等。其中,堆...
本文档总结了JVM知识点,涵盖了JVM的内存模型、垃圾回收机制、运行时数据区、对象分配、常量池、永久代、元空间等方面的知识点。 一、JVM的内存模型 JVM的内存模型分为工作内存和主内存两部分,线程无法直接操作主...
GC(垃圾回收)是JVM自动管理内存的关键机制,它能自动回收不再使用的对象占用的内存空间。JVM中垃圾回收的判定方法主要有引用计数法和引用链法。引用计数法因为无法处理相互引用的场景而未被采用,而引用链法则通过...
Object 类常用方法 Object 类是 Java 语言中的顶层类,是所有类的直接或间接父类。...自动回收机制是 JVM 的内存耗尽,一次性回收所有垃圾对象。手动回收机制是使用 System.gc(),通知 JVM 执行垃圾回收。
GC的主要任务是回收Java程序中的垃圾对象,以释放内存空间。 五、JVM知识点 1. JVM的内存模型:JVM的内存模型包括程序计数器、虚拟机栈、本地方法栈、堆、方法区五个部分。 2. 对象创建方法:对象创建方法有多种,...
- **存活对象判定**:-XX:SurvivorRatio定义Eden与Survivor区的比例。 - **垃圾收集器参数**:如-XX:+UseG1GC启用G1收集器。 4. **性能监控工具** - **JVisualVM**:内置丰富的JVM监控和分析功能,如CPU、内存、...
1. **无用对象识别**:垃圾收集器判定一个对象是否可被回收的关键标准是该对象是否仍被“活动”的部分所引用。若一个对象不再被任何变量或数据结构引用,则视为无用,可被回收。 2. **自动执行**:垃圾收集器的执行...