OOM、调优工具、调优实战

简介: OOM、调优工具、调优实战

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)

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)


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


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


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


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

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


-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

2、jstate


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



为什么说是实时呢,因为底层实现是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



3、CPU占用过高


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

  1. 定位到目前占用CPU最高的线程ID

top -H -p 6290


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


  1. 定位线程

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

练习


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

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

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



邀你加入「架构师之路」团队: https://www.yuque.com/groups/bcak73/join?token=ekRVPYE4n6zZA2fy# (成员)

相关文章
|
2月前
|
消息中间件 存储 Java
jvm性能调优实战 - 47超大数据量处理系统是如何OOM的
jvm性能调优实战 - 47超大数据量处理系统是如何OOM的
55 0
|
2月前
|
数据可视化 Java
jvm 调优工具
jvm 调优工具
38 0
|
11月前
|
监控 数据可视化 Oracle
|
Arthas 运维 监控
JVM学习.05 JVM常见的排障和调优
前面介绍了JVM相关的内存和线程相关的技术。对于JVM也算有了一个比较系统、完整的理论基础。理论总是作为指导实践的工具,但是从理论到实践,总会遇到一些虚拟机相关问题,故障。所以还需要学习一些常用的JVM排障工具,和一些常见的调优手段。
289 0
JVM学习.05 JVM常见的排障和调优
|
Java 测试技术 OLAP
聊聊JVM怎么调优(实战)
聊聊JVM怎么调优(实战)
148 0
|
传感器 安全
(0)调优
(0)调优
74 0
|
SQL 存储 NoSQL
调优建议|学习笔记
快速学习调优建议
284 0
调优建议|学习笔记
|
Java
JVM调优常用的调优参数
JVM调优常用的调优参数
141 0
|
监控 Java Unix
详解调优和监控
详解Tomcat调优和Tomcat监控
1173 0