zoukankan      html  css  js  c++  java
  • 《Java 底层原理》Jvm性能调优

    前言

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

    调优

    模拟元空间oom的情况

    import net.sf.cglib.proxy.Enhancer;
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;
    
    import java.lang.reflect.Method;
    
    public class MetaSpaceOverTest {
    
        public static void main(String[] args) throws InterruptedException {
            while (true){
                Thread.sleep(20);
    
                Enhancer enhancer = new Enhancer();
                enhancer.setSuperclass(MetaSpaceOverTest.class);
                enhancer.setUseCache(false);
                enhancer.setCallback(new MethodInterceptor() {
                    @Override
                    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                        return methodProxy.invoke(o,objects);
                    }
                });
                enhancer.create();
            }
        }
    }

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

    代码中使用了CGLib的jar包:具体说明见:https://www.cnblogs.com/jssj/p/12635206.html

    运行结果:

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

    GC日志说明:

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

    import java.util.ArrayList;
    import java.util.List;
    
    public class HeapOverTest {
    
        int[] intArr = new int[50];
    
        public static void main(String[] args) throws InterruptedException {
            List<HeapOverTest> heapOverTestList = new ArrayList<>();
            for(;;){
                Thread.sleep(1);
                heapOverTestList.add(new HeapOverTest());
            }
        }
    }
    -Xmx10m -Xms10m -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=D:

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

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

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

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

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

     

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

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

    然后找到他的引用对象:

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

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

    虚拟机栈-OOM

    public class StackOverTest {
    
        private int val = 0;
    
        public void test(){
            val++;
            test();
        }
    
        public static void main(String[] args) {
            StackOverTest stackOverTest = new StackOverTest();
            try {
                stackOverTest.test();
            } catch (Throwable e) {
                System.out.println("栈深度:"+stackOverTest.val);
            }
        }
    }

    运行结果:

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

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

    Java Agent

    待补充

    实战

    1. 死锁

    2. CPU消耗高

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

    总结

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

    This moment will nap, you will have a dream; But this moment study,you will interpret a dream.
  • 相关阅读:
    Python的集合和元组
    Python之 string 和 random方法
    Python文件读取常用方法
    Python文件读写之r+/w+/a+
    Python非空即真,非零即真
    【转】Python字符串格式化
    HTML5新增的form属性简介——张鑫旭
    CSS3选择器:nth-child和:nth-of-type之间的差异——张鑫旭
    CSS页面重构“鑫三无准则”之“无图片”准则——张鑫旭
    CSS垂直翻转/水平翻转提高web页面资源重用性——张鑫旭
  • 原文地址:https://www.cnblogs.com/jssj/p/14382863.html
Copyright © 2011-2022 走看看