深入JAVA虚拟机_ GC ROOT

本文详细介绍了Java中的垃圾回收机制,包括GC_ROOT的概念及其包含的对象类型;解释了不同类型的引用(如强引用、软引用、弱引用和虚引用)的特点及应用场景;探讨了System.gc()的作用及限制;并分析了两种主要的垃圾回收方式——新生代GC和老年代GC的过程,以及对象在堆内存中的分配策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

GC_ROOT的对象包括

1.虚拟机栈(栈帧的本地变量表)中的引用对象(方法中的参数,方法体中的局部变量)。 2.方法区中类静态属性引用的对象(static)。 3.方法区中常量引用的对象(final static)。 4.本地方法栈中JNI(Native方法)引用的对象。

强引用: 强引用就是指在程序代码中普遍存在的类似 Object oj = new Object(); 这类 的引用,只要强引用还存在,垃圾收集器永远不会回收掉被引用的对象

软引用: 用来描述一些有用但非必需的对象。对于软引用关联着的对象,***在系统将要发生内存溢出异常之前***将会把这些对象列进回收范围之类进行第二次回收。如果这次回收还没有足够的内存,才会抛出内存溢出异常。(SoftReference类实现)

弱引用: 用来描述非必需对象,但它的强度比软引用弱一些,被软引用关联的 对象***只能生存到下一次垃圾收集发生之前***。当垃圾收集器工作时无论当前内存是否足够,都会回收掉只被弱引用关联的对象。(WeakReference类实现)

虚引用: 最弱的引用关系。一个人对象是否有虚引用的存在完全不会对其生存时间造成影响,也无法通过虚引用来取得一个对象实例(其get()只能获得null)。为一个对象设置一个虚引用关联的唯一目的就是能在这个对象被回收器回收时收到一个系统通知。(PhantomReference类实现)

###System.gc() 只能提醒虚拟机程序员希望进行一次垃圾回收,但并不保证垃圾回收一定会运行,垃圾回收的进行取决虚拟机,不同的虚拟机有不同的实现。

两种GC方式:

***新生代GC(Minor GC)***:指发生在新生代的垃圾收集动作,因为Java对象大多生存时间不长,所以Minor GC非常频繁,一般回收速度也比较快。

***老年代GC(Full GC)***:指发生在老年代的GC,出现一次Full GC至少经历一次Minor GC(当Minor GC仍然满足不了空间分配才会触发Full GC)。

对象分配

大部分新生对象会在新生代Eden区分配,但Eden区没有足够空间进行分配时,会进行一次Minor GC。较大的对象([需要大量连续内存的java对象]-XX:PretenureSizeThreshold 可设置大对象的门槛)会直接分配至老年代。 长期在survivor中存活的对象每经历一次GC则其对象年龄计数器+1,当计数器的值超过某个阈值(-XX:MaxTenuringThreshold),则将该对象转至老年代。

参考: https://stackoverflow.com/questions/3329691/understanding-javas-reference-classes-softreference-weakreference-and-phanto

<think>嗯,用户问的是Java中的GCRoots有哪些,这个问题涉及到垃圾回收机制,我得仔细回忆一下相关知识。首先,GCRoots是垃圾回收的根节点,用来判断对象是否可达,进而确定是否回收。常见的GCRoots可能包括局部变量、静态变量、活动的线程这些。不过需要确认具体有哪些类型,可能需要查阅资料或者官方文档。 记得在Java中,作为GCRoot的对象包括:虚拟机栈中的本地变量表中的对象引用,也就是方法中的局部变量和参数;方法区中的类静态属性引用的对象;方法区中常量引用的对象,比如字符串常量池里的引用;还有本地方法栈中JNI引用的对象,也就是Native方法里的引用。另外,还有同步锁持有的对象,比如synchronized锁住的对象,以及虚拟机内部的一些引用,比如系统类加载器之类的。 不过需要确认这些内容是否正确,有没有遗漏或者错误的地方。比如,活动的线程是否属于GCRoots的一部分?比如Thread对象本身是否会被视为根,因为线程还在运行的话,它的栈帧里的局部变量当然会被引用。另外,像JNI全局引用和局部引用是否属于不同的类别?可能需要注意区分。 还要注意不同的垃圾收集器可能会有不同的实现,但GCRoots的基本概念应该是通用的。可能需要分点列举,确保用户能清晰理解每个类别。同时,举例子可能会有帮助,比如局部变量作为根的例子,静态变量引用的例子等。这样用户更容易明白每个GCRoot的具体应用场景。 另外,要避免使用技术术语过于复杂,需要用中文简洁明了地解释每个GCRoot的类型,并说明为什么它们被当作根节点。比如,虚拟机栈中的引用是因为方法正在执行,这些对象肯定不能被回收;静态变量因为属于类,生命周期较长等等。 可能还需要检查是否有其他类型的GCRoots,比如被JVM保留的对象,或者某些框架中的特殊引用,但通常标准的GCRoots就是那几类。所以总结下来,应该分点列出各个GCRoot,并简要说明每个的作用和存在场景。 最后,确保回答的结构清晰,分点说明,帮助用户逐步理解。如果有不确定的地方,需要确认资料的正确性,避免误导用户。</think>在 Java 中,**GC Roots** 是垃圾回收器判断对象是否存活的起点。如果一个对象无法通过 **GC Roots** 的引用链到达,则会被标记为可回收。以下是 Java 中常见的 GC Roots 类型: --- ### 1. **虚拟机栈中的局部变量** - **作用范围**:当前正在执行的方法中的局部变量和参数。 - **示例**: ```java public void example() { Object localObj = new Object(); // localObj 是 GC Root } ``` - **原因**:方法正在运行,局部变量引用的对象必须存活。 --- ### 2. **方法区中的静态变量** - **作用范围**:类的静态属性(`static` 修饰的变量)。 - **示例**: ```java public class MyClass { static Object staticObj = new Object(); // staticObj 是 GC Root } ``` - **原因**:静态变量与类生命周期绑定,通常长期存活。 --- ### 3. **方法区中的常量引用** - **作用范围**:常量池中的对象引用(如字符串常量)。 - **示例**: ```java public class MyClass { final static String CONSTANT = "Hello"; // CONSTANT 是 GC Root } ``` - **原因**:常量被类直接引用,不会被回收。 --- ### 4. **本地方法栈中的 JNI 引用** - **作用范围**:通过 JNI(Java Native Interface)调用的本地方法中的对象。 - **原因**:本地方法可能通过 C/C++ 代码持有 Java 对象的引用。 --- ### 5. **活跃线程对象** - **作用范围**:正在运行的线程对象(如 `Thread` 实例)及其栈帧中的局部变量。 - **示例**: ```java Thread thread = new Thread(() -> { /* ... */ }); // thread 是 GC Root thread.start(); ``` - **原因**:线程执行期间,其内部引用的对象必须存活。 --- ### 6. **同步锁持有的对象** - **作用范围**:通过 `synchronized` 关键字锁定的对象。 - **示例**: ```java Object lock = new Object(); synchronized (lock) { // lock 是 GC Root // ... } ``` - **原因**:锁对象在同步代码块执行期间必须存活。 --- ### 7. **JVM 内部系统对象** - **作用范围**:JVM 自身管理的对象(如系统类加载器、异常类等)。 - **原因**:JVM 需要这些对象支持其正常运行。 --- ### 总结 GC Roots 是垃圾回收的“起点”,它们共同构成对象存活的条件。理解这些根节点有助于优化内存使用,避免内存泄漏。实际开发中,可通过工具(如 `jmap`、`VisualVM`)分析对象的可达性路径。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值