如何优雅的学习JVM,实战篇(四)
# 一、JVM参数
## 1.1 标准参数
-version
-help
-server
-cp
## 1.2 -X参数
非标准参数,也就是在JDK各个版本中可能会变动
-Xint 解释执行
-Xcomp 第一次使用就编译成本地代码
-Xmixed 混合模式,JVM自己来决定
## 1.3 -XX参数
使用得最多的参数类型,非标准化参数,相对不稳定,主要用于JVM调优和Debug
a.Boolean类型
格式:-XX:\[+-\]<name> +或-表示启用或者禁用name属性
比如:-XX:+UseConcMarkSweepGC 表示启用CMS类型的垃圾回收器
-XX:+UseG1GC 表示启用G1类型的垃圾回收器
b.非Boolean类型
格式:-XX<name>=<value> 表示name属性的值是value
比如:-XX:MaxGCPauseMillis=500
## 1.4 其它参数
-Xms1000等价于 -XX:InitialHeapSize=1000
-Xmx1000等价于 -XX:MaxHeapSize=1000
-Xss1000等价于 -XX:ThreadStackSize=1000
这一块内容也相当于-XX类型的参数
## 1.5 查看参数
java -XX:+PrintFlagsFinal -version > flags.txt
上图值得注意的是“=”表示默认值,“:=”表示被用户或JVM修改后的值
一般需要设置参数,可以先查下当前参数是什么,然后再进行修改
## 1.6 设置参数的方式
* 开发工具中进行设置IDEA、eclipse
* 运行jar包的时候:java -XX:+UseG1GC xxx.jar
* Web容器比如Tomcat,可以在脚本中进行设置
* 通过**jinfo**命令实时调整某个java进程的参数(参数只有被标记位**manageable**的flags可以被实时修改)
# 1.7 单位换算和实践
1Byte(字节)=8bit(位)
1KB=1024Byte(字节)
1MB=1024KB
1GB=1024MB
1TB=1024GB
1、设置堆内存大小和参数打印
-Xmx100M -Xms100M -XX:+PrintFlagsFinal
2、查询+PrintFlagsFinal
:=true
3、查询堆内存大小MaxHeapSize
:= 104857600
4、换算
104857600(Byte)/1024=102400(KB)
102400(KB)/1024=100(MB)
5、结论
`104857600是字节单位`
# 1.8 常用参数的含义
# 二、常用命令
## 2.1 jps
查看java进程
## 2.2 jinfo
1、实时查看
`jinfo -flag name PID 查看某个java进程的name属性的值`
jinfo -flag MaxHeapSize PID
jinfo -flag UseG1GC PID
2、调整JVM配置参数
参数只有被标记为manageable的flags可以被实时修改
jinfo -flag \[+|-\] PID
jinfo -flag = PID
3、查看曾经赋过值的一些参数
`jinfo -flags PID`
## 2.3 jstat
1、查看虚拟机性能统计信息
2、查看java进程的类装载信息
jstat -class PID 1000 10 查看某个java进程的类装载信息,每1000毫秒输出一次,共输出10 次
3、查看垃圾收集信息
`jstat -gc PID 1000 10`
## 2.4 jstack
1、查看线程堆栈信息
`jstack PID`
2、排查死锁的案例
示例代码:
public class DeadLockDemo {
public static void main(String\[\] args) {
DeadLock deadLock1 = new DeadLock(true);
DeadLock deadLock2 = new DeadLock(false);
Thread thread1 = new Thread(deadLock1);
Thread thread2 = new Thread(deadLock2);
thread1.start();
thread2.start();
}
static class MyLock {
public static Object obj1 = new Object();
public static Object obj2 = new Object();
}
static class DeadLock implements Runnable {
private boolean flag;
DeadLock(boolean flag) {
this.flag = flag;
}
public void run() {
if(flag) {
while (true) {
synchronized (MyLock.obj1) {
System.out.println(Thread.currentThread().getName() + "如果获得obj1的锁");
synchronized (MyLock.obj2) {
System.out.println(Thread.currentThread().getName() + "如果获得obj2的锁");
}
}
}
}else {
while (true) {
synchronized (MyLock.obj2) {
System.out.println(Thread.currentThread().getName() + "否则获得obj2的锁");
synchronized (MyLock.obj1) {
System.out.println(Thread.currentThread().getName() + "否则获得obj1的锁");
}
}
}
}
}
}
}
运行main方法的结果
**jstack分析**
把打印信息拉到最后可以发现
## 2.5 jmap
1、生成堆转存储快照
2、打印出堆内存相关信息
-XX:+PrintFlagsFinal -Xms300M -Xmx300M
jmap -heap PID
3、dump堆内存相关信息
jmap -dump:format=b,file=heap.hprof PID
jmap -dump:format=b,file=heap.hprof 44808
4、要是能在发生堆内存溢出的时候,能自动dump出该文件就好了
一般在开发过程中,JVM参数可以加上下面两句,这样在程序内存溢出的时候,会自动dump该文件
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=heap.hprof
# 三、常用工具
## 3.1 jconsole
JConsole工具是JDK自带的可视化监控工具。查看java应用程序的运行概况、监控堆信息、永久区使用
情况、类加载情况等。
命令行中输入:jconsole
## 3.2 jvisualvm
**1、可以监控本地的java进程的CPU,类,线程等**
**2、可以监控远端tomcat,演示部署在阿里云服务器上的tomcat**
(1)在visualvm中选中“远程”,右击“添加”
(2)主机名上写服务器的ip地址,比如39.105.32.236,然后点击“确定”
(3)右击该主机“39.105.32.236”,添加“JMX”[也就是通过JMX技术具体监控远端服务器哪个Java进程]
(4)要想让服务器上的tomcat被连接,需要改一下 bin/catalina.sh 这个文件
注意下面的8998不要和服务器上其他端口冲突
JAVA\_OPTS="$JAVA\_OPTS -Dcom.sun.management.jmxremote -Djava.rmi.server.hostname=39.105.32.236 -Dcom.sun.management.jmxremote.port=8998 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=true -Dcom.sun.management.jmxremote.access.file=../conf/jmxremote.access -Dcom.sun.management.jmxremote.password.file=../conf/jmxremote.password"
(5)在 ../conf 文件中添加两个文件jmxremote.access和jmxremote.password
**jmxremote.access 文件**
guest readonly
manager readwrite
**jmxremote.password 文件**
guest guest
manager manager
授予权限 : chmod 600 *jmxremot*
(6)将连接服务器地址改为公网ip地址
hostname -i 查看输出情况
172.17.6.246 172.17.0.1
vim /etc/hosts
172.17.6.246 339.105.32.236
(7)设置上述端口对应的阿里云安全策略和防火墙策略
firewall-cmd --add-port=8080/tcp --permanent
firewall-cmd --add-port=8998/tcp --permanent
systemctl restart firewalld
(8)启动tomcat,来到bin目录
./startup.sh
(9)查看tomcat启动日志以及端口监听
tail -f ../logs/catalina.out
lsof -i tcp:8080
(10)查看8998监听情况,可以发现多开了几个端口
lsof -i:8998 得到PID
netstat -antup | grep PID
(11)在刚才的JMX中输入8998端口,并且输入用户名和密码则登录成功
端口:8998
用户名:manager
密码:manager
## 3.3 阿里的Arthas
Arthas是阿里巴巴开源的Java诊断工具,采用命令行交互模式,是排查jvm相关问题的利器。
**github:** https://github.com/alibaba/arthas
下载arthas-boot.jar,然后用java -jar的方式启动:
curl -O https://alibaba.github.io/arthas/arthas-boot.jar
java -jar arthas-boot.jar
打印帮助信息:
`java -jar arthas-boot.jar -h`
常用命令
具体每个命令怎么使用,大家可以自己查阅资料!
version:查看arthas版本号
help:查看命名帮助信息
cls:清空屏幕
session:查看当前会话信息
quit:退出arthas客户端
\-\-\-
dashboard:当前进程的实时数据面板
thread:当前JVM的线程堆栈信息
jvm:查看当前JVM的信息
sysprop:查看JVM的系统属性
\-\-\-
sc:查看JVM已经加载的类信息
dump:dump已经加载类的byte code到特定目录
jad:反编译指定已加载类的源码
\-\-\-
monitor:方法执行监控
watch:方法执行数据观测
trace:方法内部调用路径,并输出方法路径上的每个节点上耗时
stack:输出当前方法被调用的调用路径
......
## 3.4 MAT
Java堆分析器,用于查找内存泄漏
Heap Dump,称为堆转储文件,是Java进程在某个时间内的快照
**下载地址:** https://www.eclipse.org/mat/downloads.php
1、Dump信息包含的内容
* All Objects
Class, fields, primitive values and references
* All Classes
Classloader, name, super class, static fields
* Garbage Collection Roots
Objects defined to be reachable by the JVM
* Thread Stacks and Local Variables
The call-stacks of threads at the moment of the snapshot, and per-frame information about local
objects
2、获取Dump文件
* 手动
`jmap -dump:format=b,file=heap.hprof 44808`
自动
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=heap.hprof
3、使用
* Histogram
Histogram可以列出内存中的对象,对象的个数及其大小
Class Name:类名称,java类名
Objects:类的对象的数量,这个对象被创建了多少个
Shallow Heap:一个对象内存的消耗大小,不包含对其他对象的引用
Retained Heap:是shallow Heap的总和,即该对象被GC之后所能回收到内存的总和
右击类名--->List Objects--->with incoming references--->列出该类的实例
右击Java对象名--->Merge Shortest Paths to GC Roots--->exclude all ...--->找到GC Root以及原因
* Leak Suspects
查找并分析内存泄漏的可能原因
`Reports--->Leak Suspects--->Details`
* Top Consumers
列出大对象
## 3.5 GC日志分析工具
要想分析日志的信息,得先拿到GC日志文件才行,所以得先配置一下
根据前面参数的学习,下面的配置很容易看懂
-XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps
-Xloggc:gc.log
* 在线工具
https://gceasy.io/
* GCViewer
原文地址:https://www.cnblogs.com/vwvwvwgwgvervae/p/12994132.html
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- Java List.add()方法:向集合列表中添加对象
- Linux下查看NVIDIA的GPU使用情况
- 数据结构算法操作试题(C++/Python)——有效的数独
- Java List.addAll()方法:添加所有元素到列表中
- HDFS的Shell操作(开发重点)
- 数据结构算法操作试题(C++/Python)——字符串相乘
- Java基础知识笔记四(详细)
- [推荐]Linux入门系列(三)Vim编辑器(Vim工作模式+代码演示)
- 机器学习性能评价指标汇总
- [推荐]Linux入门系列(四)系统用户账号管理(代码图文示例)
- 逆波兰表达式
- 字符串:替换空格
- 字符串:花式反转还不够!
- 字符串:反转个字符串还有这个用处?
- 字符串: KMP是时候上场了(一文读懂系列)