一、JVM类加载机制——自定义类加载器
二、JVM——对象内存分配机制
三、JVM内存模型
四、JVM垃圾收集算法和垃圾收集器
五、CMS垃圾回收器——三色标记算法
六、G1垃圾收集器
七、JVM调优实战——基本命令使用
八、JVM调优实战——arthas使用
九、大流量电商系统JVM调优案例
对象栈上分配
JVM通过逃逸分析,发现对象的作用域就在某个方法内,不会被外部访问,就把对象通过标量替换之后存储在栈上。
**逃逸分析:**就是分析对象的作用域,是否能够在一个方法范围内;
**标量替换:**通过分析确定对象不会逃逸之后,JVM不会创建该对象,而是用该对象的成员变量等价替代该对象。
栈上分配依赖逃逸分析和标量替换。
package com.ysy.JVM对象创建和内存分配机制深度剖析;
/**
* @author shanyangyang
* @date 2020/7/23
* 开启逃逸分析和标量替换
* -Xmx15m -Xms15m -XX:+DoEscapeAnalysis -XX:+EliminateAllocations -XX:+PrintGC
* 只开启标量替换,关闭逃逸分析
* -Xmx15m -Xms15m -XX:-DoEscapeAnalysis -XX:+EliminateAllocations -XX:+PrintGC
开启逃逸分析,关闭标量替换
-Xmx15m -Xms15m -XX:+DoEscapeAnalysis -XX:-EliminateAllocations -XX:+PrintGC
比较三种三种情况下的GC情况
*/
public class AlloctOnStack {
public static void main(String[] args) {
long start = System.currentTimeMillis();
for (int i = 0; i < 1000000000; i++) {
alloc();
}
long end = System.currentTimeMillis();
System.out.println(end - start);
}
private static void alloc() {
User user = new User();
user.setId(1);
user.setName("ysy");
}
}
大对象直接进入老年代
JVM参数-XX:PretenureSizeThreshold可以设置大对象的大小,如果超过设置的大小,对象直接存入老年代。
**优点:**避免大对象在年轻代和老年代之间转换
package com.ysy.JVM对象创建和内存分配机制深度剖析;
/**
* @author shanyangyang
* @date 2020/7/23
* -XX:+PrintGCDetails
*/
public class GCTest {
public static void main(String[] args) {
byte[] allocation1, allocation2, allocation3, allocation4, allocation5;
allocation1 = new byte[2000 * 1024];
allocation2 = new byte[10000 * 1024];
allocation3 = new byte[8000 * 1024];
allocation4 = new byte[8000 * 1024];
allocation5 = new byte[3500 * 1025];
}
}
TLAB 本地线程分配缓存
解决分配内存的并发问题;
每个线程在java堆中预先分配一小块内存,通过-XX:+UseTLAB设置。
AGE 对象达到一定年龄会进入老年代
对象第一进入survivor区域,年龄是1岁,然后每经过一次minorGC,年龄增加1岁。可以通过参数-XX:MaxTenuringThreshold来设置,默认15岁,CMS默认6岁。
对象动态年龄判断
当前Survivor区域中的一批对象的总大小大于Suvivor区域大小的50%。
年龄1+年龄2+年龄3+…+年龄n>50%;
则把年龄大于等于N的对象转移到老年代。
老年代空间担保机制
finalize()方法
1、第一次标记并进行一次筛选。
筛选的条件是此对象是否有必要执行finalize()方法;
当对象没有覆盖这个方法时,直接回收
2、如果对象覆盖了finalize()方法;对象在该方法内部重新和GCROOT建立起连接没,就可以拯救自己。
注意:该方法只会执行一次,只有一次拯救自己的机会。