OOM、调优工具、调优实战(二)

OOM与调优

 

out of memory,即内存泄漏。哪些区域会发生OOM呢?

 

1、方法区

 

1、模拟OOM,上代码

 

第23行的cache如何理解?设置为true、false结果会有何不同?


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 MetaspaceOverFlowTest {

    /**
     * 通过CGLIB模拟向元空间写入数据
     */
    public static void main(String[] args) {
        while (true) {
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            Enhancer enhancer = new Enhancer();

            enhancer.setSuperclass(MetaspaceOverFlowTest.class);
            enhancer.setUseCache(false);
            enhancer.setCallback(new MethodInterceptor() {
                public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
                    return proxy.invokeSuper(obj, args);
                }
            });

            System.out.println("running...");

            enhancer.create();
        }
    }
}

2、如何查看(visualVM、arthas)

image.png

3、gc日志

[GC (Metadata GC Threshold) [PSYoungGen: 45765K->3280K(86528K)] 45781K->3304K(193024K), 0.0367573 secs] [Times: user=0.09 sys=0.00, real=0.04 secs] 
[Full GC (Metadata GC Threshold) [PSYoungGen: 3280K->0K(86528K)] [ParOldGen: 24K->3222K(72704K)] 3304K->3222K(159232K), [Metaspace: 9726K->9726K(1058816K)], 0.2736778 secs] [Times: user=0.54 sys=0.02, real=0.27 secs] 

4、调优参数

-XX:MetaspaceSize=10m
-XX:MaxMetaspaceSize=10m

5、调优原则

1、最大、最小设置成一样大

2、程序运行起来后,通过visualVM、arthas查看占用了多少内存,向上调优,预留20%以上的空间

 

2、堆区

 

1、模拟OOM,上代码

import java.util.ArrayList;
import java.util.List;

public class HeapOverFlowTest1 {

    int[] intArr = new int[10];

    public static void main(String[] args) {
        List<HeapOverFlowTest1> objs = new ArrayList<>();

        for (;;) {
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            objs.add(new HeapOverFlowTest1());
        }
    }
}

 

2、查看(visualVM、arthas)

image.png

 

3、gc日志

[GC (Allocation Failure) [PSYoungGen: 1344K->320K(2048K)] 7894K->7118K(9216K), 0.0071516 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] 

[GC类型 (GC原因) [新生代垃圾收集器: gc前新生代的内存使用情况->gc后新生代的内存使用情况(新生代总内存)] gc前堆内存的使用情况->gc后堆内存的使用情况(堆总内存), gc耗时] [Times: gc阶段用户空间耗时 gc阶段内核空间耗时, gc阶段实际耗时] 

[Full GC (Ergonomics) [PSYoungGen: 320K->0K(2048K)] [ParOldGen: 6798K->5930K(7168K)] 7118K->5930K(9216K), [Metaspace: 9296K->9233K(1058816K)], 0.6733958 secs] [Times: user=1.76 sys=0.00, real=0.68 secs] 

[GC类型 (GC原因) [新生代垃圾收集器: gc前新生代的内存使用情况->gc后新生代的内存使用情况(新生代总内存)] [老年代垃圾收集器: gc前老年代的内存使用情况->gc后老年代的内存使用情况(新生代总内存)] gc前堆内存的使用情况->gc后堆内存的使用情况(堆总内存), [Metaspace: gc前元空间的内存使用情况->gc后元空间的内存使用情况(元空间总内存)], gc耗时] [Times: gc阶段用户空间耗时 gc阶段内核空间耗时, gc阶段实际耗时] 

4、调优参数

-Xms10m -Xmx10m

 

5、调优原则

1、预留30%以上的空间

2、周期性看日志,重点关注full gc频率

 

3、虚拟机栈

 

1、模拟OOM,上代码

public class StackOverFlowTest {

    private int val = 0;

    public void test() {
        val++;

        test();
    }

    public static void main(String[] args) {
        StackOverFlowTest test = new StackOverFlowTest();

        try {
            test.test();
        } catch (Throwable t) {
            t.printStackTrace();

            System.out.println(test.val);
        }
    }
}

2、调优参数

-Xmss200k

 

栈大小相同,栈深度不同,为什么?

 

调优工具

 

1、jps

 

-q:只显示Java进程的ID

image.png


-m:输出Java进程的ID + main函数所在类的名词 + 传递给main函数的参数

image.png


-l:输出Java进程的ID + main函数所在类的全限定名(包名 + 类名)

image.png


-v:输出Java进程的ID + main函数所在类的名称 + 传递给JVM的参数

应用:可通过此方式快速查看JVM参数是否设置成功

image.png


-V、hostid基本用不到,这里就不做介绍了,感兴趣的同学可以自行百度学习。

 

源码在哪

 

\openjdk\jdk\src\share\classes\sun\tools\jps\

 

纯Java编写的

 

如何识别Java进程

 

jps输出的信息全是Java进程的信息,是如何做到的?

 

Java进程在创建的时候,会生成相应的文件,进程相关的信息会写入该文件中。Windows下默认理解是C:\Users\username\AppData\Local\Temp\hsperfdata_username,Linux下默认路径是/tmp/hsperfdata_username

image.png

2、jstate

 

Hotspot自带的工具,通过该工具可实时了解某个进程的class、compile、gc、memory的相关信息。具体可通过该工具查看哪些信息可通过jstat -options查看

 

image.png

 

为什么说是实时呢,因为底层实现是mmap,及内存映射文件

 


jstat输出的这些值从哪来的

 

PerfData文件

Windows下默认理解是C:\Users\username\AppData\Local\Temp\hsperfdata_username

Linux下默认路径是/tmp/hsperfdata_username

 


PerfData文件

 

1、文件创建

 

取决于两个参数

 

-XX:-/+UsePerfData

默认是开启的

关闭方式:-XX:-UsePerfData。如果关闭了,就不会创建PerfData文件



-XX:-/+PerfDisableSharedMem(禁用共享内存)

 

默认是关闭的,即支持内存共享。如果禁用了,依赖于PerfData文件的工具就无法正常工作了

 

2、文件删除

 

默认情况下随Java进程的结束而销毁

 

3、文件更新

 

-XX:PerfDataSamplingInterval = 50ms

即内存与PerfData文件的数据延迟为50ms

 


 

纯Java编写

\openjdk\jdk\src\share\classes\sun\tools\jstat\Jstat.java

 

3、jinfo

 

4、jstack

 

5、jmap

 

6、jconsole

 

7、visualVM

 

8、arthas

 

Java Agent

 

1、命令行

2、attach

 

参考文章:https://www.jianshu.com/p/f5efc53ced5d

 

实战

 

1、统计线程数

 

jstack -l 6972 | grep 'java.lang.Thread.State' | wc -l

 

2、检测死锁

 

可使用jstack、jconsle、visualVM

 

image.png

 

3、CPU占用过高

 

  1. 定位到占用CPU最高的进程

image.png

  1. 定位到目前占用CPU最高的线程ID
top -H -p 6290

image.png

 

线程ID由十进制转成十六进制,用Python

image.png

 

  1. 定位线程
jstack 6290(进程ID)|grep 18a1(线程ID,十六进制) -A 30

 

练习

 

1、自己想案例模拟OOM并思考如何调优

2、死锁、CPU占用过高问题排查,自己实际一遍

3、Java Agent的两种实现方式自己写DEMO

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值