IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> PHP知识库 -> 深入理解java虚拟机---gc root -> 正文阅读

[PHP知识库]深入理解java虚拟机---gc root

GC管理的主要区域是Java堆,一般情况下只针对堆进行垃圾回收。方法区、栈和本地方法区不被GC所管理,因而选择这些区域内的对象作为GC roots,被GC roots引用的对象不被GC回收。

GC会收集那些不是GC roots且没有被GC roots引用的对象。

------------------------------------------------------------------------------------------------------

可达性分析算法

主流的商用程序语言都是使用可达性分析(Reachability Analysis)来判定对象是否存活的

通过一系列称为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的。即需要回收的。

在Java语言里,可作为GC Roots对象的包括如下几种:?

?

  1. 虚拟机栈(栈帧中的本地变量表)中引用的对象。(方法的局部变量)
  2. 方法区中类静态属性引用的对象。(类的静态变量,使用static关键字)
  3. 方法区中常量引用的对象。(使用static final关键字修饰的常量)
  4. 本地方法栈中JNI(即一般说的Native方法)引用的对象。

?1、验证虚拟机栈(栈帧中的本地变量表)中引用的对象。(方法的局部变量)

package gcroot;

public class GCRootTest {

	private int _10MB = 10 * 1024 * 1024;
	private byte[] memory = new byte[8 * _10MB];
	public static void main(String[] args) {
		method01();
		System.out.println("返回main方法");
		System.gc();
		System.out.println("第二次GC完成");
	}
	public static void method01() {
		GCRootTest t = new GCRootTest();
		System.gc();
		System.out.println("第一次GC完成");
	}
}

eclipse gc参数设置

[GC (System.gc()) [PSYoungGen: 1996K->616K(38400K)] 83916K->82544K(125952K), 0.0646065 secs] [Times: user=0.00 sys=0.00, real=0.07 secs] 
[Full GC (System.gc()) [PSYoungGen: 616K->0K(38400K)] [ParOldGen: 81928K->82485K(87552K)] 82544K->82485K(125952K), [Metaspace: 2752K->2752K(1056768K)], 0.0583107 secs] [Times: user=0.01 sys=0.05, real=0.06 secs] 
第一次GC完成
返回main方法
[GC (System.gc()) [PSYoungGen: 665K->32K(38400K)] 83151K->82517K(125952K), 0.0030628 secs] [Times: user=0.03 sys=0.00, real=0.00 secs] 
[Full GC (System.gc()) [PSYoungGen: 32K->0K(38400K)] [ParOldGen: 82485K->565K(87552K)] 82517K->565K(125952K), [Metaspace: 2753K->2753K(1056768K)], 0.0489367 secs] [Times: user=0.03 sys=0.00, real=0.05 secs] 
第二次GC完成
Heap
 PSYoungGen      total 38400K, used 1331K [0x00000000d5d80000, 0x00000000d8800000, 0x0000000100000000)
  eden space 33280K, 4% used [0x00000000d5d80000,0x00000000d5ecce50,0x00000000d7e00000)
  from space 5120K, 0% used [0x00000000d8300000,0x00000000d8300000,0x00000000d8800000)
  to   space 5120K, 0% used [0x00000000d7e00000,0x00000000d7e00000,0x00000000d8300000)
 ParOldGen       total 87552K, used 565K [0x0000000081800000, 0x0000000086d80000, 0x00000000d5d80000)
  object space 87552K, 0% used [0x0000000081800000,0x000000008188d420,0x0000000086d80000)
 Metaspace       used 2759K, capacity 4486K, committed 4864K, reserved 1056768K
  class space    used 295K, capacity 386K, committed 512K, reserved 1048576K

[GC (System.gc()) [PSYoungGen: 1996K->616K(38400K)] 83916K->82544K(125952K), 0.0646065 secs] [Times: user=0.00 sys=0.00, real=0.07 secs]?
[Full GC (System.gc()) [PSYoungGen: 616K->0K(38400K)] [ParOldGen: 81928K->82485K(87552K)] 82544K->82485K(125952K), [Metaspace: 2752K->2752K(1056768K)], 0.0583107 secs] [Times: user=0.01 sys=0.05, real=0.06 secs]?
第一次GC完成

结果分析

第一次GC:

[GC (System.gc())

38400K为堆中年轻代的总大小,1996K->616K为年轻代的回收过程,616K为回收后的结果

125952K为堆的总大小,83916K->82544K为整个堆的回收过程

同理[Full GC (System.gc())

PSYoungGen: 616K->0K(38400K)为年轻代回收过程

ParOldGen: 81928K->82485K(87552K)为老年代回收过程

82544K->82485K(125952K)为整个堆的回收过程

可见minor gc只回收年轻代的对象,full gc会回收整个堆中的对象。

t为局部变量,引用了new出的对象(80M),作为GC Roots,在Minor GC后被转移到老年代中,且Full GC也不会回收该对象,仍保留在老年代中。

[GC (System.gc()) [PSYoungGen: 665K->32K(38400K)] 83151K->82517K(125952K), 0.0030628 secs] [Times: user=0.03 sys=0.00, real=0.00 secs]?
[Full GC (System.gc()) [PSYoungGen: 32K->0K(38400K)] [ParOldGen: 82485K->565K(87552K)] 82517K->565K(125952K), [Metaspace: 2753K->2753K(1056768K)], 0.0489367 secs] [Times: user=0.03 sys=0.00, real=0.05 secs]?
第二次GC完成

第二次GC:

method01方法执行完后,局部变量t跟随方法消失,不再有引用类型指向该对象,该对象在Full GC后,被完全回收,老年代腾出该对象之前所占的空间。

2.验证方法区中的静态变量引用的对象作为GC Roots

package gcroot;

public class GCRootTest2 {

	private static int _10MB = 10 * 1024 * 1024;
	private byte[] memory;
	private static GCRootTest2 t;

	public GCRootTest2(int size) {
		memory = new byte[size];
	}

	public static void main(String[] args) {
		GCRootTest2 t2 = new GCRootTest2(4 * _10MB);
		t2.t = new GCRootTest2(8 * _10MB);
		t2 = null;
		System.gc();
	}

}
[GC (System.gc()) [PSYoungGen: 1996K->680K(38400K)] 124876K->123568K(208384K), 0.0289990 secs] [Times: user=0.01 sys=0.00, real=0.04 secs] 
[Full GC (System.gc()) [PSYoungGen: 680K->0K(38400K)] [ParOldGen: 122888K->82485K(169984K)] 123568K->82485K(208384K), [Metaspace: 2751K->2751K(1056768K)], 0.0225445 secs] [Times: user=0.06 sys=0.00, real=0.02 secs] 
Heap
 PSYoungGen      total 38400K, used 333K [0x00000000d5d80000, 0x00000000d8800000, 0x0000000100000000)
  eden space 33280K, 1% used [0x00000000d5d80000,0x00000000d5dd34a8,0x00000000d7e00000)
  from space 5120K, 0% used [0x00000000d7e00000,0x00000000d7e00000,0x00000000d8300000)
  to   space 5120K, 0% used [0x00000000d8300000,0x00000000d8300000,0x00000000d8800000)
 ParOldGen       total 169984K, used 82485K [0x0000000081800000, 0x000000008be00000, 0x00000000d5d80000)
  object space 169984K, 48% used [0x0000000081800000,0x000000008688d630,0x000000008be00000)
 Metaspace       used 2758K, capacity 4486K, committed 4864K, reserved 1056768K
  class space    used 295K, capacity 386K, committed 512K, reserved 1048576K

?[GC (System.gc()) [PSYoungGen: 1996K->680K(38400K)] 124876K->123568K(208384K), 0.0289990 secs] [Times: user=0.01 sys=0.00, real=0.04 secs]?
[Full GC (System.gc()) [PSYoungGen: 680K->0K(38400K)] [ParOldGen: 122888K->82485K(169984K)] 123568K->82485K(208384K), [Metaspace: 2751K->2751K(1056768K)], 0.0225445 secs] [Times: user=0.06 sys=0.00, real=0.02 secs]?
t2被置为null,Minor GC后t2之前引用的对象(40M)被完全回收;t为静态变量,存放于方法区中,引用了对象(80M),在Minor GC后,被转移到老年代中,且在Full GC后,也不会被回收,继续保留在老年代中。

3.验证方法区中常量引用对象作为GC Roots

public class TestGCRoots03 {

private static int _10MB = 10 * 1024 * 1024;

private static final TestGCRoots03 t = new TestGCRoots03(8 * _10MB);

private byte[] memory;

public TestGCRoots03(int size) {

memory = new byte[size];

}

public static void main(String[] args) {

TestGCRoots03 t3 = new TestGCRoots03(4 * _10MB);

t3 = null;

System.gc();

}

}

控制台打印日志:

[GC [PSYoungGen: 138608K->688K(458752K)] 138608K->82608K(983040K), 0.0514407 secs] [Times: user=0.13 sys=0.02, real=0.05 secs]?

[Full GC [PSYoungGen: 688K->0K(458752K)] [ParOldGen: 81920K->82428K(524288K)] 82608K->82428K(983040K) [PSPermGen: 2515K->2514K(21504K)], 0.0153884 secs] [Times: user=0.06 sys=0.00, real=0.01 secs]?

t3被置为null,Minor GC后t3之前引用的对象(40M)被完全回收;t为常量,存放于方法区中,引用了对象(80M),在Minor GC后,被转移到老年代中,且在Full GC后,也不会被回收,继续保留在老年代中。

4.测试成员变量是否可作为GC Roots

public class TestGCRoots04 {

private static int _10MB = 10 * 1024 * 1024;

private TestGCRoots04 t;

private byte[] memory;

public TestGCRoots04(int size) {

memory = new byte[size];

}

public static void main(String[] args) {

TestGCRoots04 t4 = new TestGCRoots04(4 * _10MB);

t4.t = new TestGCRoots04(8 * _10MB);

t4 = null;

System.gc();

}

}

控制台打印日志:

[GC [PSYoungGen: 138608K->600K(458752K)] 138608K->600K(983040K), 0.0015591 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]?

[Full GC [PSYoungGen: 600K->0K(458752K)] [ParOldGen: 0K->507K(524288K)] 600K->507K(983040K) [PSPermGen: 2513K->2512K(21504K)], 0.0144441 secs] [Times: user=0.06 sys=0.00, real=0.02 secs]

t4被置为null,Minor GC后t4之前引用的对象(40M)被完全回收;t为成员变量,也叫实例变量,不同于类变量(静态变量),前面讲到类变量是存储在方法区中,而成员变量是存储在堆内存的对象中的,和对象共存亡,所以是不能作为GC Roots的,从日志中也可看出t在MinorGC后,跟随t4一起被完全回收。不再占用任何空间。

以上为一个非常简单的可作为GC Roots的对象的验证,不涉及较复杂的GC Roots引用链,其实作为使用者来讲,我们只要知道,哪些对象是可作为GC Roots的,在实际开发过程中要特别注意这些对象,不要让无谓的大对象消耗了资源,拖累了性能。

【证】:那些可作为GC Roots的对象icon-default.png?t=L892https://blog.csdn.net/u010798968/article/details/72835255

  PHP知识库 最新文章
Laravel 下实现 Google 2fa 验证
UUCTF WP
DASCTF10月 web
XAMPP任意命令执行提升权限漏洞(CVE-2020-
[GYCTF2020]Easyphp
iwebsec靶场 代码执行关卡通关笔记
多个线程同步执行,多个线程依次执行,多个
php 没事记录下常用方法 (TP5.1)
php之jwt
2021-09-18
上一篇文章           查看所有文章
加:2021-09-19 07:45:54  更:2021-09-19 07:48:35 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/16 13:36:49-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码