-version,-help,-server,-cp
非标准参数,也就是在JDK各个版本中可能会变动
-Xint 解释执行,-Xcomp 第一次使用就编译成本地代码,-Xmixed 混合模式,JVM自己来决定
使用得最多的参数类型,非标准化参数,相对不稳定,主要用于JVM调优和Debug。
所以这块也相当于是-XX类型的参数
java -XX:+PrintFlagsFinal -version
值得注意的是"="表示默认值,":="表示被用户或JVM修改后的值。要想查看某个进程具体参数的值,可以使用 jinfo,一般要设置参数,可以先查看一下当前参数是什么,然后进行修改。
我们可以通过IDEA进行设置参数并且打印参数信息来体会一下这个过程,首先设置堆内存大小和参数打印 -Xmx100M -Xms100M -XX:+PrintFlagsFinal
启动项目就可以看到跟上面在 CMD 窗口执行 java -XX:+PrintFlagsFinal 获取到的信息:
查询+PrintFlagsFinal的值:
查询堆内存大小MaxHeapSize , 注意这里的 104857600 (Byte) /1024 /1024 =100MB:
查看java进程:
实时查看和调整JVM配置参数 jinfo -flag name PID 查看某个java进程的 name属性的值
jinfo -flag MaxHeapSize PID :如下图显示最大堆大小
jinfo -flag UseG1GC PID :如下图未使用G1GC
参数只有被标记为manageable的 flags 可以被实时修改,jinfo -flag [+|-] PID:
jinfo -flag [+|-]name pid 描述:开启或者关闭对应名称的参数
查看曾经赋过值的一些参数 jinfo -flags PID
查看虚拟机性能统计信息,查看类装载信息,jstat -class PID 1000 10 查看某个java进程的类装载信息,每1000毫秒输出一次,共输出10次
查看垃圾收集信息 jstat -gc PID 1000 10
查看线程堆栈信息 ,jstack PID
排查死锁案例 DeadLockDemo:
public class DeadLockDemo {
public static void main(String[] args) {
DeadLock d1 = new DeadLock(true);
DeadLock d2 = new DeadLock(false);
Thread t1 = new Thread(d1);
Thread t2 = new Thread(d2);
t1.start();
t2.start();
}
}
//定义锁对象
class MyLock {
public static Object obj1 = new Object();
public static Object obj2 = new Object();
}
//死锁代码
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() + "----if 获得obj1锁");
synchronized (MyLock.obj2) {
System.out.println(Thread.currentThread().getName() + "--- -if获得obj2锁");
}
}
}
} else {
while (true) {
synchronized (MyLock.obj2) {
System.out.println(Thread.currentThread().getName() + "----否则 获得obj2锁");
synchronized (MyLock.obj1) {
System.out.println(Thread.currentThread().getName() + "--- -否则获得obj1锁");
}
}
}
}
}
}
运行结果:
jps 查看进程并且打印栈信息:
将打印的信息拉到最下面会发现死锁的信息:
生成堆转储快照,打印出堆内存相关信息,先设置虚拟机参数:-XX:+PrintFlagsFinal -Xms300M -Xmx300M,然后启动。
dump出堆内存相关信息:jmap -dump:format=b,file=heap.hprof PID 。要是在发生堆内存溢出的时候,能自动dump出该文件就好了一般在开发中,JVM参数可以加上下面两句,这样内存溢出时,会自动dump出该文件,设置 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=heap.hprof 即可在OOM的时候dump出该文件。关于dump下来的文件,一般dump下来的文件可以结合工具来分析。
参数也了解了,命令也知道了,关键是用起来不是很方便,要是有图形化的界面就好了。一定会有好事之者来做这件事情。
JConsole工具是JDK自带的可视化监控工具。查看java应用程序的运行概况、监控堆信息、永久区使用情况、类加载情况等。在${JAVA+HOME}/bin下面找到并打开
远程连接需要配置:
java -Djava.rmi.server.hostname=10.160.13.111 #远程服务器ip,即本机ip -Dcom.sun.management.jmxremote #允许JMX远程调用 -Dcom.sun.management.jmxremote.port=3214 #自定义jmx 端口号 -Dcom.sun.management.jmxremote.ssl=false # 是否需要ssl 安全连接方式 -Dcom.sun.management.jmxremote.authenticate=false #是否需要秘钥 -jar test.jar
在${JAVA+HOME}/bin下面找到并打开,监控本地Java进程:可以监控本地的java进程的CPU,类,线程等
监控远端Java进程:比如监控远端tomcat,部署在阿里云服务器上的tomcat
在visualvm中选中“远程”,右击“添加”
主机名上写服务器的ip地址,比如192.168.1.101,然后点击“确定”
右击该主机“192.168.1.101”,添加“JMX”[也就是通过JMX技术具体监控远端服务器哪个Java进程]
要想让服务器上的tomcat被连接,需要改一下 bin/catalina.sh 这个文件.注意下面的8998不要和服务器上其他端口冲突:
JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote -Djava.rmi.server.hostname=192.168.1.101 -Dcom.sun.management.jmxremote.port=8998 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=true -Dcom.sun.ma
nagement.jmxremote.access.file=../conf/jmxremote.access -Dcom.sun.management.jmxremote.password.file=../conf/jmxremote.password"
在 ../conf 文件中添加两个文件jmxremote.access和jmxremote.password,jmxremote.access 文件:
guest readonly
manager readwrite
jmxremote.password 文件:
guest guest
manager manager
授予权限 : chmod 600 *jmxremot*
github :https://github.com/alibaba/arthas 。Arthas 是Alibaba开源的Java诊断工具,采用命令行交互模式,是排查jvm相关问题的利器。Arthas 是Alibaba开源的Java诊断工具,深受开发者喜爱。当你遇到以下类似问题而束手无策时,Arthas 可以帮助你解决:
Arthas 支持JDK 6+,支持Linux/Mac/Windows,采用命令行交互模式,同时提供丰富的 Tab 自动补全功能,进一步方便进行问题的定位和诊断。
curl -O https://alibaba.github.io/arthas/arthas-boot.jar java -jar arthas-boot.jar # 然后可以选择一个Java进程
启动后选择对应的Java进程:
Print usage :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:输出当前方法被调用的调用路径 ......
Dump信息包含的内容
获取Dump文件
@RestController public class HeapController { Listlist=new ArrayList (); @GetMapping("/heap") public String heap() throws Exception{ while(true){ list.add(new Person()); Thread.sleep(1); } } }
启动springboot,访问上面这个接口造成内存溢出。
使用:
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 ...--->找到GCRoot以及原因。如下图我们会发现EntityDemo这个类得实例有10W多个。
Leak Suspects:查找并分析内存泄漏的可能原因Reports--->Leak Suspects--->Details
他就会告诉我们哪里存在问题,然后我们就可以粗略定位到问题,然后去看代码就能定位到。以上就是关于JVM得内存信息得获取及分析得一些简单介绍。