p134 垃圾回收相关章节的说明
p135 什么是GC 为什么需要GC
P136 了解早起垃圾回收行为
p137 java自动内存管理介绍
p138垃圾回收相关算法概述
p139引用计数算法的原理及优缺点
p140 python引用计数实施方案
p141 可达性分析算法与GC ROOTS
p142 对象的finalization机制
p143 代码演示可复活的对象
public class CanReliveObj {
// 类变量,属于GC Roots的一部分
public static CanReliveObj canReliveObj;
@Override
protected void finalize() throws Throwable {
super.finalize();
System.out.println("调用当前类重写的finalize()方法");
canReliveObj = this;
}
public static void main(String[] args) throws InterruptedException {
canReliveObj = new CanReliveObj();
canReliveObj = null;
System.gc();
System.out.println("-----------------第一次gc操作------------");
// 因为Finalizer线程的优先级比较低,暂停2秒,以等待它
Thread.sleep(2000);
if (canReliveObj == null) {
System.out.println("obj is dead");
} else {
System.out.println("obj is still alive");
}
System.out.println("-----------------第二次gc操作------------");
canReliveObj = null;
System.gc();
// 下面代码和上面代码是一样的,但是 canReliveObj却自救失败了
Thread.sleep(2000);
if (canReliveObj == null) {
System.out.println("obj is dead");
} else {
System.out.println("obj is still alive");
}
}
}
p144使用MAT查看GC ROOTS
p145使用JProfile进行GC Roots溯源
import java.util.ArrayList;
public class TestHeap {
public static void main(String[] args) throws InterruptedException {
ArrayList<Object> list = new ArrayList<>();
while (true){
byte[] bytes = new byte[102400];
Thread.sleep(10);
list.add(bytes);
}
}
}
p146 使用JProfiler分析OOM
超大对象导致oom
p147 标记-清除算法及优缺点
p148 复制算法原理及优缺点
p149 标记-压缩算法原理及优缺点
p150 不同指标上对比三种算法
p151 分代收集算法的说明
p152 增量收集算法原理及优缺点
p153分区算法的说明
p154 垃圾回收相关概念的概述
略
p155System.gc()的理解
public class SystemGCTest {
public static void main(String[] args) {
new SystemGCTest();
System.gc();// 提醒JVM的垃圾回收器执行gc,但是不确定是否马上执行gc
// 与Runtime.getRuntime().gc();的作用一样
System.runFinalization();//强制执行使用引用的对象的finalize()方法
}
@Override
protected void finalize() throws Throwable {
super.finalize();
System.out.println("SystemGCTest 重写了finalize()");
}
}
p156 手动gc理解不可达对象的回收行为
p157内存溢出的分析
p158内存泄露的分析
p159 stopTheWorld事件的理解
p165软引用 内存不足即回收
import java.lang.ref.SoftReference;
/**
* 软引用的测试:内存不足即回收
*
* @author shkstart shkstart@126.com
* @create 2020 16:06
*/
public class SoftReferenceTest {
public static class User {
public User(int id, String name) {
this.id = id;
this.name = name;
}
public int id;
public String name;
@Override
public String toString() {
return "[id=" + id + ", name=" + name + "] ";
}
}
public static void main(String[] args) {
//创建对象,建立软引用
// SoftReference<User> userSoftRef = new SoftReference<User>(new User(1, "songhk"));
//上面的一行代码,等价于如下的三行代码
User u1 = new User(1,"songhk");
SoftReference<User> userSoftRef = new SoftReference<User>(u1);
u1 = null;//取消强引用
//从软引用中重新获得强引用对象
System.out.println(userSoftRef.get());
System.gc();
System.out.println("After GC:");
// //垃圾回收之后获得软引用中的对象
System.out.println(userSoftRef.get());//由于堆空间内存足够,所有不会回收软引用的可达对象。
//
try {
//让系统认为内存资源紧张、不够
// byte[] b = new byte[1024 * 1024 * 7];
byte[] b = new byte[1024 * 7168 - 635 * 1024];
} catch (Throwable e) {
e.printStackTrace();
} finally {
//再次从软引用中获取数据
System.out.println(userSoftRef.get());//在报OOM之前,垃圾回收器会回收软引用的可达对象。
}
}
}
p166弱引用 发现即回收
package com.atguigu.java1;
import java.lang.ref.WeakReference;
/**
* 弱引用的测试
*
* @author shkstart shkstart@126.com
* @create 2020 16:06
*/
public class WeakReferenceTest {
public static class User {
public User(int id, String name) {
this.id = id;
this.name = name;
}
public int id;
public String name;
@Override
public String toString() {
return "[id=" + id + ", name=" + name + "] ";
}
}
public static void main(String[] args) {
//构造了弱引用
WeakReference<User> userWeakRef = new WeakReference<User>(new User(1, "songhk"));
//从弱引用中重新获取对象
System.out.println(userWeakRef.get());
System.gc();
// 不管当前内存空间足够与否,都会回收它的内存
System.out.println("After GC:");
//重新尝试从弱引用中获取对象
System.out.println(userWeakRef.get());
}
}