004-JVM-Java中使用的标记阶段的算法:可达性分析算法中GC Roots有哪些
作者:互联网
上一篇:003-JVM-标记阶段的算法:怎么确定垃圾 https://blog.csdn.net/fsjwin/article/details/111322134
gc roots有哪些呢?这个是面试题,也要背下来,如果不想进大厂的话,可以不背。
1. 常规gc roots
-
- JVM stack
虚拟机栈中引用的对象
比如: 各个线程被调用的方法中使用到的参数、局部变量等
- JVM stack
-
- nativ method stack
JNI( 通常说的本地方法) 引用的对象
- nativ method stack
-
- runtime constant pool
运行时常量池
- runtime constant pool
-
- static references in method area
(堆jdk8)中类静态属性引用的对象
比如: Java 类的引用类型静态变量
(堆jdk8) 中常量引用的对象
比如: 字符串常量池(String Table ) 里的引用
- static references in method area
-
- Clazz
Java 虚拟机内部的引用。
基本数据类型对应的Class对象, 一些常驻的异常对象( 如:NullPointerException 、OutOfMemoryError) , 系统类加载器
- Clazz
-
- 所有被同步锁synchronized持有的对象
- 所有被同步锁synchronized持有的对象
除了这些固定的GC Roots集合以外, 根据用户所选用的垃圾收集器以及当前回收的内存区域不同, 还可以有其他对象“ 临时性” 地加入, 共同构成完整GC Roots 集合。比如: 分代收集和局部回收( Partial GC)
如果只针对Java 堆中的某一块区域进行垃圾回收( 比如: 典型的只针对新生代) , 必须考虑到内存区域是虚拟机自己的实现细节, 更不是孤立封闭的, 这个区域的对象完全有可能被其他区域的对象所引用,这时候就需要一并将关联的区域对象也加入GC Roots集合中去考虑, 才能保证可达性分析的准确性。
局部回收:意思如果分代回收的时候,比如对年轻代进行回收,那么在老年代中的变量(其指向了年轻代。),也需要放入Roots Set中。否则就会出现误伤!
小技巧:由于Root采用栈方式存放变量和指针, 所以如果一个指针, 它保存了堆内存里面的对象, 但是自己又不存放在堆内存里面, 那它就是一个Root。
2. 临时 gc roots
除了这些固定的GC Roots集合以外, 根据用户所选用的垃圾收集器以及当前回收的内存区域不同, 还可以有其他对象“ 临时性” 地加入, 共同构成完整GC Roots 集合。比如: 分代收集和局部回收( Partial GC)
- 如果只针对Java 堆中的某一块区域进行垃圾回收( 比如: 典型的只针对新生代) , 必须考虑到内存区域是虚拟机自己的实现细节, 更不是孤立封闭的, 这个区域的对象完全有可能被其他区域的对象所引用,这时候就需要一并将
关联的区域对象也加入GC Roots集合中
去考虑, 才能保证可达性分析的准确性。 - 局部回收:意思如果分代回收的时候,比如对年轻代进行回收,
那么在老年代中的变量(其指向了年轻代。)
,也需要放入Roots Set中。否则就会出现误伤!
小技巧:由于Root采用栈方式存放变量和指针, 所以如果一个指针, 它保存了堆内存里面的对象, 但是自己又不存放在堆内存里面, 那它就是一个Root。(此说法不严谨:比如上面提到的 “ 临时性” 地加入的;jdk8中的StringTable、Static变量等,均在堆中。
但是可以作为一般的评判标准)
3. 总结
- 常规的6中需要在roots set中
- 特殊的两种在roots set 中。
标签:Java,对象,回收,算法,区域,GC,内存,可达性,Roots 来源: https://blog.csdn.net/fsjwin/article/details/111322956