Overview
- 定位Java进程
- Java 进程状态
- Java 启动参数
- Jvm 调优实战
- Other Command
以下命令和测试均在Java8环境执行,有些命令可能因版本情况不适用.
定位java进程
- 利用java命令查看进程情况
jps -l
->/proc/pid
- 利用系统命令搜索进程
ps -ef |grep "process_name"
Java 进程状态
java进程状态有哪些?
- 查看的pid (即如何定位java进程)
- 当前进程启动的参数信息
- 所占用的内存 cpu 磁盘空间等
- jvm状态(gc信息 堆信息 栈信息等)
当前进程启动的参数信息
本机的初始化参数: java -XX:+PrintFlagsInitial
进程启动参数: jps -v
可以查看java进程启动时所带的参数信息
进程占用端口: netstat -anpo |grep pid
进程情况: ps -ef |grep pid
所占用的内存 cpu 磁盘空间等
内存占用情况 pmap -d pid
循环打印内存占用 while true; do pmap -d 3447 | tail -1; sleep 2; done
文件夹大小 du -sh dir_name
当前磁盘大小 df -h .
ls -l 命令显示的是这个目录节点信息占的大小,du 命令计算的这个目录下所有文件数据的总和。
线程状态
linux 进程的线程数: pstree -p pid
ps -Lf pid
jvm 当前线程数: jstack pid | grep 'java.lang.Thread.State' | wc -l
当前线程都处于什么状态: jstack pid | 'java.lang.Thread.State' | grep 'java.lang.Thread.State' | sort | uniq -c |sort -n
线程状态含义 及监测
9 java.lang.Thread.State: RUNNABLE
2 java.lang.Thread.State: TIMED_WAITING (parking)
1 java.lang.Thread.State: TIMED_WAITING (sleeping)
2 java.lang.Thread.State: WAITING (on object monitor)
18 java.lang.Thread.State: WAITING (parking)
java 线程状态文章 => jstack java线程
JVM状态
jvm内存占用状态: jmap -heap
线上gc查看: jstat -gc pid
栈日志导出: jstack pid > jstack.log
堆日志导出: jmap -dump:format=b,file=heap.log pid
查找内存占用: jmap -histo pid| head -20
GC原因查询: jstat -gccause pid
类加载器时间: jstat -class pid
查看垃圾收集器默认=> java -XX:+PrintCommandLineFlags -version
查看垃圾收集器当前进程 => jmap -heap pid |grep GC
Concurrent Mark-Sweep GC :CMS回收器
Mark Sweep Compact GC:串行GC(Serial GC)
Parallel GC with 2 thread(s): 并行GC(ParNew)
Java 启动参数
- jvm版本对应的启动参数
- 启动参数分类(额外日志型,项目优化)
Official Guide
官方文档 | 描述 |
---|---|
Java HotSpot VM Options | HotSpotVM 参数 |
Java SE 8 Documentation | Java8 参数文档 |
Java11 Virtual Machine Guide | Java11 虚拟机指引 |
项目常见参数配置
其配置的就是 堆、栈、元空间、新生代老年代、垃圾收集器。
①堆
的大小 一般设置成一样的,防止内存在增加或者减少时的内存抖动
-Xms1024m (堆最大大小)
-Xmx1024m (堆默认大小)
②栈
的最大深度大小 其值越大 创建线程数越少,其值越小 栈的深度越小
-Xss256k (棧最大深度大小)
③元空间
大小 spring boot在启动时会load大量的类和卸载大量的类
-XX:MetaspaceSize=128m (元空间默认大小)
-XX:MaxMetaspaceSize=128m (元空间最大大小)
④Other 其他
-Xmn256m (新生代大小)
-XX:SurvivorRatio=8 (新生代分区比例 8:2)
-XX:+UseConcMarkSweepGC (指定使用的垃圾收集器,这里使用CMS收集器)
-XX:+PrintGCDetails (打印详细的GC日志)
知识点:
JDK8之后把-XX:PermSize 和 -XX:MaxPermGen移除了,取而代之的是
-XX:MetaspaceSize=128m (元空间默认大小)
-XX:MaxMetaspaceSize=128m (元空间最大大小)
元空间 => JDK 8开始把类的元数据放到本地化的堆内存(native heap)中,这一块区域就叫Metaspace.
使用本地化的内存有什么好处呢?最直接的表现就是java.lang.OutOfMemoryError: PermGen 空间问题将不复存在。不过,让Metaspace变得无限大显然是不现实的,因此我们也要限制Metaspace的大小:
使用-XX:MaxMetaspaceSize参数来指定Metaspace区域的大小。JVM默认在运行时根据需要动态地设置MaxMetaspaceSize的大小。
Spring Boot 项目启动就进行FullGc的问题
以前只认为,Metaspace区是保存在本地内存中,是没有上限的,经查阅资料才发现,原来JDK8中,XX:MaxMetaspaceSize确实是没有上限的,最大容量与机器的内存有关;但是XX:MetaspaceSize是有一个默认值的:21M。问题就出在这里。
JVM关于元空间配置
问题 => 在工作过程中,遇到一个问题:Tomcat在重启或者发布的时候,会有多次的full GC。
额外日志
GC日志信息
-verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps
输出gc日志到文件 -Xloggc:/path/to/gc.log
完整命令 java -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -Xloggc:gc.log
打印类加载信息
类加载 卸载信息 -XX:+TraceClassLoading -XX:+TraceClassUnloading
java命令行信息
要获取VM命令行,请运行
jcmd pid VM.command_line
要查看JVM标志的完整列表,请运行
jcmd pid VM.flags -all
JVM 调优实战
首先为什么要调优?
- 优化项目的性能,即减少GC
- 减少应用的内存占用
- 优化到什么程度
调优步骤:
-
获取项目的jvm配置及相关信息
jps -v
-
获取项目的gc信息
jstat -gccause
-
获取项目的垃圾收集器和现在一些信息
jmap -heap
判断是否出现了内存泄露 使用jmap -histo:live
可以强制进行FGC:
存泄露的判断方法是,当请求不断增加,有一部分内存没有被释放.内存没有被释放.认为即对象没有被释放->
jmap -dump:live,file=path
这个命令会进行full gc,并且输出文件 Jprofile
-
对指标进行调优 FGC次数 理想状态FGC次数 频次越低越好(综合来看) 但是FGC次数的降低一般意味着内存的占用提升
-
调整JVM 启动参数 .... 并加以观测
常见手段
调整堆大小到合适大小,减少GC次数
适当通过 -Xmn”命令调节新生代大小,最大限度降低新对象直接进入老年代的情况
性能指标
MinorGC 执行时间不到50ms; Minor GC 执行不频繁,约10秒一次; Full GC 执行时间不到1s; Full GC 执行频率不算频繁,不低于10分钟1次。
内存泄露观测
jmap -dump:format=b,file=myfile.hprof pid
一般文件都比较大需要压缩 => 比如用 zip xxx.zip file
在7000端口启动服务,貌似查不出来啥: jhat file.hprof
以下是两个内存观测工具
JVM 查看对象大小
jmap -histo pid | head -20
System.out.println(RamUsageEstimator.sizeOf(root))
<!--jol-core-->
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-core</artifactId>
<version>4.0.0</version>
</dependency>
代码层面优化
减少创建对象的数量; 减少使用全局变量和大对象;
Other Command
项目管理
- 生成软连接
ln -s from to (文件,文件夹都可链接)
影响线上程序
- 进行强制Gc
jmap -histo:live
常见java command
jinfo 命令
使用 jinfo 可以在不重启虚拟机的情况下,可以动态的修改 jvm 的参数。尤其在线上的环境特别有用
jinfo -flag +PrintGCDetails pid
jinfo -flag +PrintGC pid
实用的工具
IDEA debug线上代码
java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=9190 -jar debug-demo.jar
tcpdump抓包
tcpdump -i eth0 -A -s0 port 9052
-i 指定网卡 -A 表示使用 ASCII 字符串打印报文的全部数据 -s0 捕获所有数据,默认只抓96字节
写在最后
以上命令要不断练习,在练习过程中不断体会jvm原理等.