java jvm性能调优_《Java 底层原理》Jvm性能调优

前言

Java 的性能调优,主要就是为了防止出现out of memory(oom)。Java出现oom就会直接导致程序停止运行。

调优

模拟元空间oom的情况

importnet.sf.cglib.proxy.Enhancer;importnet.sf.cglib.proxy.MethodInterceptor;importnet.sf.cglib.proxy.MethodProxy;importjava.lang.reflect.Method;public classMetaSpaceOverTest {public static void main(String[] args) throwsInterruptedException {while (true){

Thread.sleep(20);

Enhancer enhancer= newEnhancer();

enhancer.setSuperclass(MetaSpaceOverTest.class);

enhancer.setUseCache(false);

enhancer.setCallback(newMethodInterceptor() {

@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throwsThrowable {returnmethodProxy.invoke(o,objects);

}

});

enhancer.create();

}

}

}

需要设置的参数:-XX:+PrintGCDetails -XX:MetaspaceSize=20M -XX:MaxMetaspaceSize=20M      分别是打印GC日志,设置元空间的内存初始值的最大值。

运行结果:

98d335c15db6e59238eee73b7479ce7f.png

Metaspace 空间出现oom的情况,通过jvisualvm 工具可以比较清楚的看到元空间的使用情况。

c2830ce9d9c1509fd7074fbc3589b17f.png

GC日志说明:

[GC (Metadata GC Threshold) [PSYoungGen: 555K->128K(35328K)] 4349K->3922K(105472K), 0.0012436 secs] [Times: user=0.00 sys=0.00, real=0.00secs]

[Full GC (Metadata GC Threshold) [PSYoungGen: 128K->0K(35328K)] [ParOldGen: 3794K->3789K(108544K)] 3922K->3789K(143872K), [Metaspace: 19831K->19831K(1067008K)], 0.0169102 secs] [Times: user=0.02 sys=0.00, real=0.02 secs]

GC (Metadata GC Threshold): 这是一个young GC,表示GC作用的内存位置,Metadata是元空间的意思。

[PSYoungGen: 555K->128K(35328K)] :这是一个youngGC 新生代堆区从555K 变成 128K, 新生代堆区总大小是35328K。

4349K->3922K(105472K) :总堆区从4349K到3922K, 总堆区的大小105472K。

0.0012436 secs:GC消耗的时间。

Full GC (Metadata GC Threshold) : 这是一个Full GC。

[PSYoungGen: 128K->0K(35328K)]:新生代对象占用内存移动到了老年代。

[ParOldGen: 3794K->3789K(108544K)]:老年代堆区从3794K->3789K。

3922K->3789K(143872K):整个堆区的变化情况。

[Metaspace: 19831K->19831K(1067008K)]:元空间的占用内存的变化情况。这里可以看到已经快超20M。

重点:方法区调优,-XX:MetaspaceSize=20M -XX:MaxMetaspaceSize=20M 两个参数设置一样大,程序运行后查询元空间被使用的情况,在这个基础上加20%的。查看元空间的使用情况可以使用工具:jvisualvm

模拟堆区的oom

importjava.util.ArrayList;importjava.util.List;public classHeapOverTest {int[] intArr = new int[50];public static void main(String[] args) throwsInterruptedException {

List heapOverTestList = new ArrayList<>();for(;;){

Thread.sleep(1);

heapOverTestList.add(newHeapOverTest());

}

}

}

-Xmx10m -Xms10m -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=D:

Jvm 参数设置堆的最大最小内存大小和打印GC日志, 剩下的是用于打印日志和将Heap信息的日志存放到D盘。

运行结果:(运行一段时间会出现这个报错。)

59959e3d8e1bb07b46f5eca257ab2454.png

利用该工具可以很好的看出来堆内存的使用情况。

3289d1314e39d3645f48bcac257dea4a.png

根据前面的信息,我们已经获取到一个HeapOOM的日志,我们来分析看看。

62b07c264709732b9bf47b5ddb47edef.png

上传日志分析,点击类视图,查看什么对象比较占用内存。

988090bcd4d330fa97053a942c9da759.png

可以比较明显的看出什么比较暂用内存。当然生产环境会比这个大很多很多,分析也会更加复杂。

这里的int[] 我们其实还不知道具体是被哪个对象引用,所以我需要查看被引用对象。

bcb3101b4f62d89cd559310c8b62a632.png

然后找到他的引用对象:

c6d0d52de6733eb727e3457f24d2ee70.png

堆区调优:堆区最大值和最小值调整一样大,防止内存抖动,具体调整多大根据程序正常运行下再加30%。

-Xmx10m 设置堆内存的最大值-Xms10m 设置堆内存的最小值

虚拟机栈-OOM

public classStackOverTest {private int val = 0;public voidtest(){

val++;

test();

}public static voidmain(String[] args) {

StackOverTest stackOverTest= newStackOverTest();try{

stackOverTest.test();

}catch(Throwable e) {

System.out.println("栈深度:"+stackOverTest.val);

}

}

}

运行结果:

ba8abedbdc9dfc00da66213ec886193e.png

这个栈深度每次运行会出现略微的差别:原因是因为会出现栈上分配,轻量级锁的存在。

-Xss100K 设置虚拟机栈大小,部分机器最小要求不同

Java Agent

待补充

实战

1. 死锁

e234c7c72ca264d6460c7e9ed1909c07.png

2. CPU消耗高

top -H -p 6290 --6290是进程号

总结

Jvm性能调优是Java工程师的必修课。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值