JVM调优实战——jvm常用参数及方法
创始人
2024-05-15 04:05:25
0

一、创建会内存溢出的程序

pom:

4.0.0com.fanJVMTest1.0-SNAPSHOTorg.apache.maven.pluginsmaven-shade-plugin3.2.0packageshade{Mainclass}com.fan.T15_Fu11GC_Problem01org.apache.maven.pluginsmaven-compiler-plugin88jarJVMTesthttp://maven.apache.orgUTF-8junitjunit3.8.1testorg.apache.tomcat.embedtomcat-embed-core9.0.58backport-util-concurrentbackport-util-concurrent3.1

Java:

package com.fan;import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;public class T15_Fu11GC_Problem01 {private static ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(50, new ThreadPoolExecutor.DiscardOldestPolicy());public static void main(String[] args) throws Exception {executor.setMaximumPoolSize(50);for (; ; ) {modelFit();Thread.sleep(100);}}private static class CardInfo {BigDecimal price = new BigDecimal(0.0);String name = "张三";int age = 5;Date birihdate = new Date();public void m() {}}private static void modelFit() {List taskList = getAllCardInfo();taskList.forEach(info -> {executor.scheduleWithFixedDelay(() -> {info.m();}, 2, 3, TimeUnit.SECONDS);});}private static List getAllCardInfo() {List taskList = new ArrayList<>();for (int i = 0; i < 100; i++) {CardInfo ci = new CardInfo();taskList.add(ci);}return taskList;}
}

打包 jar:

 将 JVMTest-1.0-SNAPSHOT.jar 包放到服务器中 

 二、启动 JVMTest-1.0-SNAPSHOT.jar

java -Xms200M -Xmx200M -XX:+PrintGC -jar JVMTest-1.0-SNAPSHOT.jar 

如图,随着时间的推移,GC每隔一段时间回收一次。

jvm排查常用命令: 

1. jps:该命令会显示所有的 java进程,这里我们的测试程序为 4869 jar

  

2. jinfo 进程号: 该命令显示 对应进程号进程的相关信息

[root@centos142 arthas]# jinfo 4869
Attaching to process ID 4869, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.333-b02
Java System Properties:java.runtime.name = Java(TM) SE Runtime Environment
java.vm.version = 25.333-b02
sun.boot.library.path = /usr/local/jdk1.8/jre/lib/amd64
java.vendor.url = http://java.oracle.com/
java.vm.vendor = Oracle Corporation
path.separator = :
file.encoding.pkg = sun.io
java.vm.name = Java HotSpot(TM) 64-Bit Server VM
sun.os.patch.level = unknown
sun.java.launcher = SUN_STANDARD
user.country = CN
user.dir = /mnt/arthas
java.vm.specification.name = Java Virtual Machine Specification
java.runtime.version = 1.8.0_333-b02
java.awt.graphicsenv = sun.awt.X11GraphicsEnvironment
os.arch = amd64
java.endorsed.dirs = /usr/local/jdk1.8/jre/lib/endorsed
java.io.tmpdir = /tmp
line.separator = java.vm.specification.vendor = Oracle Corporation
os.name = Linux
sun.jnu.encoding = UTF-8
java.library.path = /usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib
java.specification.name = Java Platform API Specification
java.class.version = 52.0
sun.management.compiler = HotSpot 64-Bit Tiered Compilers
os.version = 3.10.0-1160.el7.x86_64
user.home = /root
user.timezone = 
java.awt.printerjob = sun.print.PSPrinterJob
file.encoding = UTF-8
java.specification.version = 1.8
user.name = root
java.class.path = JVMTest-1.0-SNAPSHOT.jar
java.vm.specification.version = 1.8
sun.arch.data.model = 64
sun.java.command = JVMTest-1.0-SNAPSHOT.jar
java.home = /usr/local/jdk1.8/jre
user.language = zh
java.specification.vendor = Oracle Corporation
awt.toolkit = sun.awt.X11.XToolkit
java.vm.info = mixed mode
java.version = 1.8.0_333
java.ext.dirs = /usr/local/jdk1.8/jre/lib/ext:/usr/java/packages/lib/ext
sun.boot.class.path = /usr/local/jdk1.8/jre/lib/resources.jar:/usr/local/jdk1.8/jre/lib/rt.jar:/usr/local/jdk1.8/jre/lib/sunrsasign.jar:/usr/local/jdk1.8/jre/lib/jsse.jar:/usr/local/jdk1.8/jre/lib/jce.jar:/usr/local/jdk1.8/jre/lib/charsets.jar:/usr/local/jdk1.8/jre/lib/jfr.jar:/usr/local/jdk1.8/jre/classes
java.vendor = Oracle Corporation
file.separator = /
java.vendor.url.bug = http://bugreport.sun.com/bugreport/
sun.io.unicode.encoding = UnicodeLittle
sun.cpu.endian = little
sun.cpu.isalist = VM Flags:
Non-default VM flags: -XX:CICompilerCount=2 -XX:InitialHeapSize=209715200 -XX:MaxHeapSize=209715200 -XX:MaxNewSize=69730304 -XX:MinHeapDeltaBytes=524288 -XX:NewSize=69730304 -XX:OldSize=139984896 -XX:+PrintGC -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:+UseParallelGC 
Command line:  -Xms200M -Xmx200M -XX:+PrintGC

 例如,这里我们启动的程序使用的是  -Xms200M -Xmx200M -XX:+PrintGC

3.  jstat  -[gc] 进程号 [500]:该命令用来统计或跟踪 java 的进程信息。

(1)、动态观察 GC 情况(阅读 GC日志发现频繁GC 、arthas观察、jvisualVM、Jprofiler等)。

[root@centos142 arthas]# jstat -gc 4869S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT   
8192.0 8192.0  0.0    0.0   50688.0  50040.7   136704.0   136606.0  4864.0 4113.3 512.0  446.4       5    0.304  12      5.061    5.366

(2)、每500毫秒刷新一次,用来跟踪内存的增长过程

[root@centos142 arthas]# jstat -gc 4869 500S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT   
8192.0 8192.0  0.0    0.0   50688.0  50551.2   136704.0   136606.0  4864.0 4113.3 512.0  446.4       5    0.304  21      8.917    9.221
8192.0 8192.0  0.0    0.0   50688.0  50600.3   136704.0   136606.0  4864.0 4113.3 512.0  446.4       5    0.304  21      8.917    9.221
8192.0 8192.0  0.0    0.0   50688.0  50653.5   136704.0   136606.0  4864.0 4113.3 512.0  446.4       5    0.304  21      8.917    9.221
8192.0 8192.0  0.0    0.0   50688.0  50653.5   136704.0   136606.0  4864.0 4113.3 512.0  446.4       5    0.304  21      8.917    9.221
8192.0 8192.0  0.0    0.0   50688.0  50653.5   136704.0   136606.0  4864.0 4113.3 512.0  446.4       5    0.304  21      8.917    9.221
8192.0 8192.0  0.0    0.0   50688.0  50653.5   136704.0   136606.0  4864.0 4113.3 512.0  446.4       5    0.304  21      8.917    9.221
8192.0 8192.0  0.0    0.0   50688.0  50655.6   136704.0   136606.0  4864.0 4113.3 512.0  446.4       5    0.304  21      8.917    9.221
8192.0 8192.0  0.0    0.0   50688.0  50688.0   136704.0   136606.0  4864.0 4113.3 512.0  446.4       5    0.304  22      8.917    9.221
8192.0 8192.0  0.0    0.0   50688.0  50039.5   136704.0   136606.0  4864.0 4113.3 512.0  446.4       5    0.304  22      9.302    9.606

注意:图形界面用在测试的时候, 压测观察,而不是用在生产环境下定位OOM。

4. jstack 4869 :该命令会显示 所有的线程(线程名、线程编号、线程优先级、操作系统级的优先级、线程的状态、线程的调用堆栈)的信息。如:多个线程的状态一直是 waiting on condition  ,则说明程序可能产生了死锁。

如何找到哪个线程持有这把锁?

       搜索 jstack dump 的信息,找,看哪个线程持有这把锁 RUNNABLE。

[root@centos142 arthas]# jstack 4869
"pool-1-thread-45" #52 prio=5 os_prio=0 tid=0x00007fda34290000 nid=0x133d waiting on condition [0x00007fd9e2bea000]java.lang.Thread.State: WAITING (parking)at sun.misc.Unsafe.park(Native Method)- parking to wait for  <0x00000000f82aef40> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1088)at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)at java.lang.Thread.run(Thread.java:750)
"pool-1-thread-44" #51 prio=5 os_prio=0 tid=0x00007fda3428e000 nid=0x133c waiting on condition [0x00007fd9e2ceb000]java.lang.Thread.State: WAITING (parking)at sun.misc.Unsafe.park(Native Method)- parking to wait for  <0x00000000f82c4af8> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836)at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:870)at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1199)

5. 系统级命令,top、top - Hp 进程号,top:查看当前进程占内存情况top - Hp 进程号:查看进程号中所有线程的内存、cup情况。

6. jmap 作用1:

        a、jmap -histo 进程号: 对当前 jvm 的所有对象进行分析,查看哪些类有多少个对象,占多大字节。

        b、jmap -histo 进程号 | head -20 :查看最占内存的前20个对象是哪些。

 jmap 作用2:

        jmap -dump:format=b,file=20230121.hprof 进程号  :产生一个java的整个堆内存的转储文件,对它进行分析。

注意:jmap是不可以在 生成环境下执行的,会产生一个很严重的后果:jmap会让 jvm 卡死在某个状态,线上系统,内存特别大,jmap执行期间会对进程产生很大影响,甚至卡顿(电商不适合)

        1:设定了参数HeapDump,OOM的时候会自动产生堆转储文件(不是很专业,因为多有监控,内存增长就会报警)

        2:很多服务器备份(高可用) ,停掉这台服务器对其他服务器不影响

        3:在线定位(一般小点儿公司用不到)
        4:在测试环境中压测(产生类似内存增长问题,在堆还不是很大的时候进行转储)

JVM常见排查流程:

1. 使用 top 找出哪个进程占用 cpu 比较高。

2. 使用 top -Hp 进程号,找到这个进程中哪个线程占用 cpu 高。

3. 根据线程编号通过 jstack 查看调用链路。一般分为俩种情况:

        a、vm GC

        b、业务线程,找业务方法占用高的

4. 如果是 vm GC,查看日志,看看原因是什么。如:访问量压力大(扩容机器)、内存回收不掉。

5. 一般启动项目的时候会设置,当进程出现 OOM后,自动生成dump文件。通过工具对dump文件进行分析。

java -Xms200M -Xmx200M -XX:+UseParallelGC -XX:+HeapDumpOnOutOfMemoryError java文件或 jar包

以上所有命令,都可以被 arthas 替代,arthas更方便、更全面!,学习arthas地址:

Arthas 入门到实战(一)快速入门_明湖起风了的博客-CSDN博客 

相关内容

热门资讯

【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
Android|无法访问或保存... 这个问题可能是由于权限设置不正确导致的。您需要在应用程序清单文件中添加以下代码来请求适当的权限:此外...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
AsusVivobook无法开... 首先,我们可以尝试重置BIOS(Basic Input/Output System)来解决这个问题。...
ASM贪吃蛇游戏-解决错误的问... 要解决ASM贪吃蛇游戏中的错误问题,你可以按照以下步骤进行:首先,确定错误的具体表现和问题所在。在贪...
月入8000+的steam搬砖... 大家好,我是阿阳 今天要给大家介绍的是 steam 游戏搬砖项目,目前...