开章,不知道有没有小伙伴跟我一样,在快要毕业或者换工作的时候疯狂刷八股文,这样做有什么坏处呢
- 好多面试题自己都是靠死记硬背,这也是我们过后压根记不着这些内容的原因;
- 每次面试问题需要自己反复去刷,甚至工作的时候有人谈到了,自己都需要取翻看知识点;
- 在面试的时候有些问题不熟悉,又担心被面试官问到,提心吊胆。
于是,我萌生了一个想法,如果我把问题全部搞懂呢,
- 会不会有工作帮助呢?
- 会不会拓宽我们的思路呢?
- 会不会让面试官刮目相看呢?(可以跟面试官聊一下自己探索问题的过程)。
在 Java 编程中,垃圾回收(Garbage Collection)是一个非常重要的概念,用于管理内存中不再被引用的对象,并释放它们占用的内存空间。但要理解垃圾回收是如何工作的,首先需要了解什么是 JVM GC Root。
什么是GC Root
GC Root(垃圾回收根对象)是指那些被直接引用的对象,它们不会被垃圾回收机制回收。GC Root 对象通常是内存中的起始点,垃圾回收器从这些对象开始跟踪和清理内存中不再被引用的对象,以释放内存空间。
GC Root 对象通常包括以下几种类型:
- 局部变量表(Local Variables)中的对象引用: 这包括当前执行线程中的本地变量、方法参数和返回值等。
- 本地方法栈中的对象引用: 本地方法栈是用于执行本地(非 Java)方法的栈,其中也包含对象引用。
- 活动线程(Active Threads): 活动线程本身被认为是 GC Root,因为它们持有对线程本地变量表的引用,这些变量可能引用其他对象。
- 静态变量(Static Variables): 静态变量属于类而不是实例,因此它们在整个应用程序生命周期内都存在,并且可以被认为是 GC Root。
- JNI 引用(JNI References): 如果 Java 代码使用 Java Native Interface (JNI) 调用了本地代码,JNI 引用的对象也被认为是 GC Root。
- 类加载器: 类加载器也可以被认为是 GC Root,因为它们负责加载类及其相关资源,从而保持了对类的引用。
- 常量池中的对象(Objects in Constant Pool): 常量池中的字符串常量和其他常量通常也被认为是 GC Root,因为它们是全局的,并且可以在整个应用程序的生命周期内访问。
这里我尝试运行了一个测试程序,并导出dump文件,通过软件,我们可以看到活动线程、常量池中的对象作为了GC Root,这里就不一一截图,有兴趣的小伙伴可以自己探索。
对象存活的判断
- 引用计数法(Reference Counting):
引用计数法是一种简单的垃圾回收算法,它通过在每个对象上维护一个引用计数器,记录着指向该对象的引用数量。当引用数量减少到零时,表示该对象不再被引用,可以被回收。
优点:
- 简单,实现容易。
- 可以迅速地判断对象是否存活。
缺点:
- 无法解决循环引用问题。如果两个或多个对象相互引用,但与其他对象无关,它们的引用计数永远不会减为零,导致无法回收。
- 需要额外的内存空间来存储引用计数器,增加了内存开销。
- 需要维护引用计数器的增减操作,可能会影响程序性能。
-
可达性分析法(Reachability Analysis):
可达性分析法是一种更广泛使用的垃圾回收算法,它基于对象之间的引用关系来判断对象是否存活。它从一组称为 GC Roots 的起始对象出发,通过遍历对象引用关系图,找到所有可以从 GC Roots 访问到的对象,而其他对象则被判定为不可达,可以被回收。
在这里插入图片描述
优点:
- 能够解决循环引用问题,因为只要这些对象与 GC Roots 之间没有引用链相连,它们都会被回收。
- 不需要维护引用计数器,减少了内存开销。
- 适用于复杂的对象引用关系。
缺点:
- 需要进行全局性的遍历和分析,可能会消耗较多的 CPU 和内存资源,造成一定的性能损失。
- 可能导致一些短期存活的对象被错误回收(假阴性),或者长期不被回收的对象占用内存(假阳性)。
通过工具我们可以看到哪些对象引用了GCRoot
在现代的 JVM 中,可达性分析法是主要采用的垃圾回收方式,因为它能够有效处理循环引用问题,同时也能够处理复杂的对象引用关系。虽然它需要进行更多的计算和分析,但 JVM 的优化和多线程处理能够降低其性能开销。
总的来说,可达性分析法是 JVM 中判断对象存活性的主要方式,而引用计数法在实际应用中较少使用,主要因为它无法解决循环引用问题。
总结
通过了解什么是 GC Root 对于我们来说是非常有帮助的,特别是在处理内存管理和垃圾回收方面,以下是一些好处:
- 内存泄漏诊断: GC Root 是对象保留在内存中的原因之一。了解 GC Root 可以帮助你识别潜在的内存泄漏问题,即对象被无意中保留在内存中,导致内存消耗过多的情况。
- 垃圾回收优化: 了解哪些对象是 GC Root 可以帮助你更好地理解垃圾回收的工作原理。这有助于你编写更具效率的代码,减少不必要的对象保留,从而减少垃圾回收的频率和成本。
- 性能调优: 通过了解 GC Root 对象,你可以识别潜在的性能瓶颈,特别是在内存使用方面。这有助于你优化代码以提高应用程序的性能和响应时间。
- 代码审查和维护: 了解 GC Root 可以帮助你在代码审查和维护过程中更好地理解代码中对象的生命周期,特别是在多线程环境中。这有助于你避免潜在的并发问题。
- 故障排除: 当应用程序发生内存相关的故障时,了解 GC Root 可以帮助你快速定位问题并进行故障排除。
需要与博主做技术交流的请加QQ(1719120364),博主喜欢动漫、本子、里番、switch游戏(有志同道合的可加)