Skip to content

Commit c0823a1

Browse files
jvm学习
1 parent 5cd5add commit c0823a1

2 files changed

Lines changed: 197 additions & 0 deletions

File tree

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
package com.sun.jvm.Jvm.finalize;
2+
3+
/**
4+
* @ClassName FinalizeEscapeGC
5+
* @Despacito TODO
6+
* @Author chenzhuo
7+
* @Version 1.0
8+
* Finalize导致gc失效
9+
* finalize 放在 finalize-Queue中 在一个低级的线程中执行
10+
* finalize() 只能被执行一次
11+
* finalize的执行流程:
12+
* finalize流程:当对象变成(GC Roots)不可达时,GC会判断该对象是否覆盖了finalize方法,
13+
* 若未覆盖,或则已经执行完finalize方法
14+
* 则直接将其回收.否则,若对象未执行过finalize方法,将其放入F-Queue队列,
15+
* 由一低优先级线程执行该队列中对象的finalize方法.
16+
* 执行finalize方法完毕后,GC会再次判断该对象是否可达,若不可达,则进行回收,否则,对象"复活".
17+
* 对象可由两种状态,涉及到两类状态空间,一是终结状态空间 F = {unfinalized, finalizable, finalized};
18+
* 二是可达状态空间 R = {reachable, finalizer-reachable, unreachable}.各状态含义如下:
19+
* unfinalized: 新建对象会先进入此状态,GC并未准备执行其finalize方法,因为该对象是可达的(没有执行finalize,系统也不准备执行. )
20+
*
21+
* finalizable: 表示GC可对该对象执行finalize方法,GC已检测到该对象不可达.正
22+
* 如前面所述,GC通过F-Queue队列和一专用线程完成finalize的执行
23+
* (可以执行finalize了,系统会在随后的某个时间执行finalize.)
24+
* finalized: 表示GC已经对该对象执行过finalize方法
25+
*
26+
* reachable: 表示GC Roots引用可达
27+
*
28+
* finalizer-reachable(f-reachable):表示不是reachable,但可通过某个finalizable对象可达,
29+
* 除了reachable外,从F-Queue可以通过引用到达的对象.
30+
*
31+
* unreachable:对象不可通过上面两种途径可达(reachable,finalizer-reachable)
32+
*finalize问题:
33+
* finalize-Queue是由一个低级的线程去执行的,jvm不保证这个一定会执行完,
34+
* 因为finalize-Queue在执行的时候可能出现了死循环,会导致整个回收系统的奔溃
35+
*
36+
**/
37+
public class FinalizeEscapeGC {
38+
public static FinalizeEscapeGC SAVE_HOOK = null;
39+
40+
public void isAlive() {
41+
System.out.println("我还存活");
42+
}
43+
44+
@Override
45+
protected void finalize() throws Throwable {
46+
super.finalize();
47+
System.out.println("执行 finalize");
48+
//对象的状态由unreachable变成reachable,就是对象复活
49+
SAVE_HOOK = this;
50+
}
51+
52+
public static void main(String[] args) throws InterruptedException {
53+
54+
//当前状态是新建 unfinalized
55+
SAVE_HOOK = new FinalizeEscapeGC();
56+
//第一次自救成功
57+
//对象为null,就变成了不可达,finalizable
58+
//从unfinalized --- 变成了 finalizable
59+
SAVE_HOOK = null;
60+
//finalizable 执行过gc
61+
//添加到f-queue中
62+
//然后变成了finalizer-reachable 队列可达
63+
System.gc();
64+
Thread.sleep(500);
65+
if (null != SAVE_HOOK) {
66+
SAVE_HOOK.isAlive();
67+
} else {
68+
System.out.println("SAVE_HOOK 已经被回收");
69+
}
70+
71+
//第二次自救失败
72+
SAVE_HOOK = null;
73+
//这里系统已经标记过了,所以回收 第二次回收失败
74+
System.gc();
75+
Thread.sleep(500);
76+
if (null != SAVE_HOOK) {
77+
SAVE_HOOK.isAlive();
78+
} else {
79+
System.out.println("11111SAVE_HOOK 已经被回收");
80+
}
81+
}
82+
}
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
package com.sun.jvm.Jvm.gcRoots;
2+
3+
/**
4+
* @ClassName GCRootTest
5+
* @Despacito TODO
6+
* @Author chenzhuo
7+
* @Version 1.0
8+
* -Xmx200M -Xms200M -Xmn100M -XX:+UseParNewGC -XX:+UseConcMarkSweepGC
9+
* -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=75 -XX:+PrintGCDetails
10+
* gc回收算法
11+
* 可达回收算法
12+
* 这个算法的基本思路就是通过一系列的称为"GC Roots"的对象作为起始点,
13+
* 从这些节点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain),
14+
* 当一个对象到GC Roots没有任何引用链相时,则证明此对象是不可用的
15+
* next 这个是可以达到但是next 却没有引用 所以gc在回收的时候 需要遍历next 这个对象
16+
* next = null 直接赋值为null,可以帮助gc
17+
* {@link java.util.concurrent.locks.AbstractQueuedSynchronizer}
18+
* acquireQueued
19+
* final boolean acquireQueued(final Node node, int arg) {
20+
* boolean failed = true;
21+
* try {
22+
* boolean interrupted = false;
23+
* for (;;) {
24+
* final Node p = node.predecessor();
25+
* if (p == head && tryAcquire(arg)) {
26+
* setHead(node);
27+
* p.next = null; // help GC
28+
* failed = false;
29+
* return interrupted;
30+
* }
31+
* if (shouldParkAfterFailedAcquire(p, node) &&
32+
* parkAndCheckInterrupt())
33+
* interrupted = true;
34+
* }
35+
* } finally {
36+
* if (failed)
37+
* cancelAcquire(node);
38+
* }
39+
* }
40+
*
41+
* 在Java语言中,可作为GC Roots的对象包括下面几种:
42+
* 虚拟机栈(栈帧中的本地变量表)中引用的对象。
43+
* 方法区中类静态属性引用的对象。
44+
* 方法区中常量引用的对象。
45+
* 本地方法栈中JNI(即一般说的Native方法)引用的对象。
46+
**/
47+
public class GCRootTest {
48+
private static final int _1MB = 1024 * 1024;
49+
private static final int LENGTH = 40000000;
50+
51+
/**
52+
* gc日志
53+
* [GC (Allocation Failure) [ParNew: 1064551K->133120K(1198080K), 15.8236844 secs] 1064551K->938838K(3962880K), 15.8237292 secs] [Times: user=113.70 sys=1.11, real=15.82 secs]
54+
* Heap
55+
* par new generation total 1198080K, used 1131502K [0x00000006c6000000, 0x0000000717400000, 0x0000000717400000)
56+
* eden space 1064960K, 93% used [0x00000006c6000000, 0x0000000702efb898, 0x0000000707000000)
57+
* from space 133120K, 100% used [0x000000070f200000, 0x0000000717400000, 0x0000000717400000)
58+
* to space 133120K, 0% used [0x0000000707000000, 0x0000000707000000, 0x000000070f200000)
59+
* concurrent mark-sweep generation total 2764800K, used 805718K [0x0000000717400000, 0x00000007c0000000, 0x00000007c0000000)
60+
* Metaspace used 3741K, capacity 4540K, committed 4864K, reserved 1056768K
61+
* class space used 409K, capacity 428K, committed 512K, reserved 1048576K
62+
*
63+
* @param args
64+
*/
65+
public static void main(String[] args) {
66+
Node next = null;
67+
for (int i = 0; i <= LENGTH; i++) {
68+
Node node = new Node(i, next);
69+
next = node;
70+
}
71+
/**
72+
* gc日志
73+
* [GC (Allocation Failure) [ParNew: 1064551K->847K(1198080K), 0.0038396 secs] 1064551K->847K(3962880K), 0.0039093 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
74+
* Heap
75+
* par new generation total 1198080K, used 967281K [0x00000006c6000000, 0x0000000717400000, 0x0000000717400000)
76+
* eden space 1064960K, 90% used [0x00000006c6000000, 0x0000000700fc8548, 0x0000000707000000)
77+
* from space 133120K, 0% used [0x000000070f200000, 0x000000070f2d3ff0, 0x0000000717400000)
78+
* to space 133120K, 0% used [0x0000000707000000, 0x0000000707000000, 0x000000070f200000)
79+
* concurrent mark-sweep generation total 2764800K, used 0K [0x0000000717400000, 0x00000007c0000000, 0x00000007c0000000)
80+
* Metaspace used 3223K, capacity 4500K, committed 4864K, reserved 1056768K
81+
* class space used 349K, capacity 388K, committed 512K, reserved 1048576K
82+
*/
83+
// next = null; help gc
84+
triggerGC();
85+
}
86+
87+
private static void triggerGC() {
88+
//new一个大对象 它可能直接就到old区去了。
89+
// byte[] all = new byte[2000 * _1MB];
90+
for (int i = 0; i < 500; i++) {
91+
byte[] bytes = new byte[2 * _1MB];
92+
}
93+
}
94+
95+
static class Node {
96+
private int valuel;
97+
private Node node;
98+
public Node(int valuel, Node node) {
99+
this.valuel = valuel;
100+
this.node = node;
101+
}
102+
public int getValuel() {
103+
return valuel;
104+
}
105+
public void setValuel(int valuel) {
106+
this.valuel = valuel;
107+
}
108+
public Node getNode() {
109+
return node;
110+
}
111+
public void setNode(Node node) {
112+
this.node = node;
113+
}
114+
}
115+
}

0 commit comments

Comments
 (0)