JVM学习(6)-JVM工具以及GC调优策略

一.JVM工具

一.命令行工具

1.jps

jsp命令用于查看所有的Java进程以及进程传入参数、虚拟机参数等。

  • jps 「查看所有Java进程名称」
 ~  jps
18451 KafkaDemoApplication
18452 Launcher
18507 Jps
  • jps -l 「查看所有Java进程启动类」
 ~  jps -l
18451 com.iteason.kafka_demo.KafkaDemoApplication
18515 sun.tools.jps.Jps
18452 org.jetbrains.jps.cmdline.Launcher
  • jps -v 「查看所有Java进程启动时的JVM参数」
 ~  jps -v
18451 KafkaDemoApplication -XX:TieredStopAtLevel=1 -Xverify:none -Dspring.output.ansi.enabled=always -Dcom.sun.management.jmxremote -Dspring.jmx.enabled=true -Dspring.liveBeansView.mbeanDomain -Dspring.application.admin.enabled=true -javaagent:/Applications/IntelliJ IDEA.app/Contents/lib/idea_rt.jar=54489:/Applications/IntelliJ IDEA.app/Contents/bin -Dfile.encoding=UTF-8
18452 Launcher -Xmx700m -Djava.awt.headless=true -Djava.endorsed.dirs="" -Djdt.compiler.useSingleThread=true -Dpreload.project.path=/Users/arong/MyFile/Project/kafka_demo -Dpreload.config.path=/Users/arong/Library/Preferences/IntelliJIdea2019.2/options -Dcompile.parallel=false -Drebuild.on.dependency.change=true -Djava.net.preferIPv4Stack=true -Dio.netty.initialSeedUniquifier=4645090984170935302 -Dfile.encoding=UTF-8 -Duser.language=zh -Duser.country=CN -Didea.paths.selector=IntelliJIdea2019.2 -Didea.home.path=/Applications/IntelliJ IDEA.app/Contents -Didea.config.path=/Users/arong/Library/Preferences/IntelliJIdea2019.2 -Didea.plugins.path=/Users/arong/Library/Application Support/IntelliJIdea2019.2 -Djps.log.dir=/Users/arong/Library/Logs/IntelliJIdea2019.2/build-log -Djps.fallback.jdk.home=/Applications/IntelliJ IDEA.app/Contents/jbr/Contents/Home -Djps.fallback.jdk.version=11.0.4 -Dio.netty.noUnsafe=true -Djava.io.tmpdir=/Users/arong/Library/Caches/IntelliJIdea2019.2/compile-server/kafka_demo_f56d0ae1/_temp_ -Djps.backwardw
  • jps -m 「输出所有Java进程中传递给main函数的参数」
 ~ jps -m
18451 KafkaDemoApplication
18452 Launcher /Applications/IntelliJ IDEA.app/Contents/lib/asm-all-7.0.1.jar:/Applications/IntelliJ IDEA.app/Contents/lib/lz4-java-1.6.0.jar:/Applications/IntelliJ IDEA.app/Contents/plugins/java/lib/maven-aether-provider-3.3.9.jar:/Applications/IntelliJ IDEA.app/Contents/plugins/java/lib/aether-connector-basic-1.1.0.jar:/Applications/IntelliJ IDEA.app/Contents/plugins/java/lib/plexus-utils-3.0.22.jar:/Applications/IntelliJ IDEA.app/Contents/plugins/java/lib/aether-api-1.1.0.jar:/Applications/IntelliJ IDEA.app/Contents/lib/httpclient-4.5.9.jar:/Applications/IntelliJ IDEA.app/Contents/plugins/java/lib/maven-model-builder-3.3.9.jar:/Applications/IntelliJ IDEA.app/Contents/lib/netty-codec-4.1.38.Final.jar:/Applications/IntelliJ IDEA.app/Contents/plugins/java/lib/maven-builder-support-3.3.9.jar:/Applications/IntelliJ IDEA.app/Contents/plugins/java/lib/jps-builders-6.jar:/Applications/IntelliJ IDEA.app/Contents/plugins/java/lib/javac2.jar:/Applications/IntelliJ IDEA.app/Contents/plugins/java/li
18695 Jps -m

2.jstat

jstat工具用于分析JVM运行的各项数据,如新生代大小、老年代大小、Young GC次数、Full GC次数等等,是命令行下最好的JVM运行数据分析工具。

使用格式:jstat --< option> < pid> < per_second>

例如

jstat --gc 1999 1s

表示的是使用jstat工具查看pid为1999的进程的JVM运行数据,并且每1s钟刷新一次。

常见的 option 如下:

  • jstat -class :显示 ClassLoader 的相关信息
  • jstat -compiler :显示 JIT 编译的相关信息
  • jstat -gc :显示与 GC 相关的堆信息
  • jstat -gccapacity :显示各个代的容量及使用情况
  • jstat -gcnew :显示新生代信息
  • jstat -gcnewcapcacity :显示新生代大小与使用情况
  • jstat -gcold :显示老年代和永久代的信息
  • jstat -gcoldcapacity :显示老年代的大小
  • jstat -gcpermcapacity :显示永久代大小
  • jstat -gcutil:显示垃圾收集信息

3.jinfo

jinfo工具用于实时地查看并修改已启动的虚拟机的各项参数。

使用格式:

  1. jinfo pid:查看该pid下的JVM启动参数。
  2. jinfo -flag [-/+]name 可以查看特定的参数,使用-/+在前面标示参数表明关闭或开启。
  3. jinfo -flag name=value可以修改特定参数值。
 ~  jps
19060 KotlinCompileDaemon
18452 Launcher
19270 Launcher
19271 miann
19559 Jps
 ~  jinfo -flag MaxHeapSize 19271
-XX:MaxHeapSize=2147483648
 ~  jinfo -flag PrintGC 19271
-XX:-PrintGC  // PrintGC选项关闭
 ~  jinfo -flag +PrintGC 19271 // 开启PrintGC选项
 ~  jinfo -flag PrintGC 19271 
-XX:+PrintGC

4.jstack

jstack用于分析当前时刻线程的执行状态,常用来发现死锁发生在哪个线程。

~  jstack 19821
Found one Java-level deadlock:
=============================
"线程 B":
  waiting to lock monitor 0x000000000333e668 (object 0x00000000d5efe1c0, a java.lang.Object),
  which is held by "线程 A"
"线程 A":
  waiting to lock monitor 0x000000000333be88 (object 0x00000000d5efe1d0, a java.lang.Object),
  which is held by "线程 B"

Java stack information for the threads listed above:
===================================================
"线程 B":
        at DeadLockDemo.lambda$main$1(DeadLockDemo.java:31)
        - waiting to lock <0x00000000d5efe1c0> (a java.lang.Object)
        - locked <0x00000000d5efe1d0> (a java.lang.Object)
        at DeadLockDemo$$Lambda$2/1078694789.run(Unknown Source)
        at java.lang.Thread.run(Thread.java:748)
"线程 A":
        at DeadLockDemo.lambda$main$0(DeadLockDemo.java:16)
        - waiting to lock <0x00000000d5efe1d0> (a java.lang.Object)
        - locked <0x00000000d5efe1c0> (a java.lang.Object)
        at DeadLockDemo$$Lambda$1/1324119927.run(Unknown Source)
        at java.lang.Thread.run(Thread.java:748)

Found 1 deadlock.

5.jmap

jmap用于生成堆转储快照,用于分析OOM异常。
jmap(Memory Map for Java)命令用于生成堆转储快照。 如果不使用 jmap 命令,要想获取 Java 堆转储,可以使用 -XX:+HeapDumpOnOutOfMemoryError启动参数,可以让虚拟机在 OOM 异常出现之后自动生成 heapdump 文件,Linux 命令下可以通过 kill -3 发送进程退出信号也能拿到 dump 文件。

6.jhat

jhat用于分析jmap生成的 heapdump 文件或发生OOM而备份的heapdump文件,它会建立一个 HTTP/HTML 服务器,让用户可以在浏览器上查看分析结果。

二.图形化工具

1.JConsole

Java自带等jconsole图形化工具,可以很好地分析Java进程的JVM各项参数:
如果配置了JDK环境变量的话,直接在终端输入jconsole即可打开图形化工具.
在这里插入图片描述

在这里插入图片描述

2.VirtualVM

VisualVM 提供在 Java 虚拟机 (Java Virutal Machine, JVM) 上运行的 Java 应用程序的详细信息。在 VisualVM 的图形用户界面中,可以方便、快捷地查看多个 Java 应用程序的相关信息。和JConsole类似,不过提供了更强大的功能和分析图。一般来说JConsole已经够用了。

二.GC调优策略

1.什么是GC调优

GC调优的作用是通过调整JVM的启动参数,来减少 Full GC的频率和新生代对象转移到老年代的数量[本质上还是要减少Full GC的频率]。

2.GC调优原则

  1. 应该在应用启动时进行合适等JVM参数配置,而不是在应用运行的过程中。
  2. 大多数导致GC问题的情况下,都是代码出现问题。
  3. GC调优是在改变代码逻辑后仍无法达到目的的情况下才使用的,默认的JVM参数适合大部分情景。
  4. 尽量少地创建大对象和全局变量对象。

2.常用的JVM启动参数

在这里插入图片描述

3.GC调优策略

无需GC调优的情况

  1. Minor GC执行时间不到50ms

  2. Minor GC执行不频繁,约10秒一次

  3. Full GC执行时间不到1s

  4. Full GC执行频率不算频繁,不低于10分钟1次

1.将对象尽可能分配到新生代

JVM的对象分配策略中,第一条就是将对象首先分配到新生代中。因为老年代发生Full GC的停顿时间远多于新生代发生Majar GC。一般可以根据服务器内存大小以及通过jstatjconsole来查看应用的新时代内存分配情况及占用率,通过-xmn参数设置更大的新时代空间。

2.将大对象分配到老年代

JVM的对象分配策略第二条就是将大对象分配到老年代。为什么不将大对象分配到新生代呢?因为如果在分配新生代的话,需要进行大量内存的复杂过程(from Servivor -> to Servivor),并且如果to Servivor空间不够用了,还需要进行担保分配,会消耗很多时间,所以不如一开始就将大对象分配到老年代,通过-XX:PretenureSizeThreshold可以设置直接进入老年代对象的大小。

3.合理设置新生代转移到老年代的年龄

合理设置进入老年代对象的年龄,通过-XX:MaxTenuringThreshold 设置对象进入老年代的年龄大小,减少老年代的内存占用,降低 Full gc 发生的频率。

Thanks

JVM面试问题系列:JVM 配置常用参数和常用 GC 调优策略

发布了309 篇原创文章 · 获赞 205 · 访问量 30万+

猜你喜欢

转载自blog.csdn.net/pbrlovejava/article/details/103496312