一、前言
除开java与javac,你还知道JDK的其他命名吗?
虚拟机故障处理与调优一般怎么处理?
JDK强大而且小巧的工具,可以帮助我们实现很多骚操作,如果线上服务器你实在难以近身,还提供了tools.jar的类库以备你在应用程序中实现强大监控功能,让你骚起来。同时帮你解决一些虚拟机故障。
二、虚拟机性能监控
2.1JPS:虚拟机进程状况工具
jps命令:jps [options] [hostid]
选项 | 作用 |
---|---|
-q | 只输出LIMID,省略主类的名称 |
-m | 输出虚拟机进程启动时候传递给main()函数的参数 |
-l | 输出主类的全名,如果进程执行的Jar包,输出的Jar路径 |
-v | 输出虚拟机进程启动时候的参数 |
示例如下:
ycydeMacBook-Pro:~ ycy$ jps -l
96506 org.jetbrains.jps.cmdline.Launcher
96509 sun.tools.jps.Jps
ycydeMacBook-Pro:~ ycy$
2.2jstat:虚拟机统计信息监视工具
它显示进程汇总的类加载、内存、垃圾收集、JIT等数据。
jstat命令格式:jstat [option vmid ] [interval [s|ms] [count]]
选项 | 作用 |
---|---|
-class | 监视类装载、卸载数量、总空间以及类装载所消耗的时间 |
-gc | 监视Java堆状况、包括Eden区、两个Survivor区、老年代、永久带等 容量等信息 |
-gccapacity | 监视信息与gc相同,关注各个区域使用的最大、最小空间 |
-gcuti | 监视信息与gc相同,关注使用空间占总空间的百分比 |
-gcnew | 监视新生代GC情况 |
-gcnewcapacity | 与gcnew相同,关注使用最大、最小空间 |
-gcold | 监视老年代GC情况 |
-gcoldcapacity | 关注使用最大、最小空间 |
-gcpermcapatity | 输出永久代最大、最小空间 |
-compiler | 输出JIT编译过的方法、耗时 |
-printcompilation | 输出已经被JIT编译过的方法 |
实例如下
ycydeMacBook-Pro:~ ycy$ jps -l
96506 org.jetbrains.jps.cmdline.Launcher
96988 sun.tools.jps.Jps
ycydeMacBook-Pro:~ ycy$ jstat -gcutil 96506
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
0.00 47.75 50.90 0.05 96.69 90.64 1 0.006 0 0.000 0.006
ycydeMacBook-Pro:~ ycy$
2.3jinfo:Java配置信息工具
实时查询虚拟机参数
jinfo命令格式:jinfo [options] pid
ycydeMacBook-Pro:~ ycy$ jinfo 96506
Attaching to process ID 96506, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.71-b15
Java System Properties:
os.name = Mac OS X
java.vm.specification.vendor = Oracle Corporation
java.runtime.version = 1.8.0_71-b15
·····
2.4jmap:Java内存映像工具
查询finalize执行队列、Java堆和永久代信息,使用哪种收集器等。
选项 | 作用 |
---|---|
-dump | 生成存储快照 格式:-dump [live,] format=b,file=,其中live说明是否只是dump存活的对象 |
-finalizerinfo | 线上F-Queue在县城执行finalize方法对象 |
-heap | 显示使用回收器、参数配置,分代情况 |
-histo | 显示堆中统计信息,包括类、实例数量、合计内容 |
-permstat | 以ClassLoader为统计口径显示永久代状态 1.8无 |
ycydeMacBook-Pro:~ ycy$ jps -l
97077 sun.tools.jps.Jps
96506 org.jetbrains.jps.cmdline.Launcher
ycydeMacBook-Pro:~ ycy$ jmap -heap 96506
Attaching to process ID 96506, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.71-b15
using thread-local object allocation.
Parallel GC with 8 thread(s)
Heap Configuration:
MinHeapFreeRatio = 0
MaxHeapFreeRatio = 100
MaxHeapSize = 734003200 (700.0MB)
NewSize = 89128960 (85.0MB)
MaxNewSize = 244318208 (233.0MB)
OldSize = 179306496 (171.0MB)
NewRatio = 2
SurvivorRatio = 8
MetaspaceSize = 21807104 (20.796875MB)
CompressedClassSpaceSize = 1073741824 (1024.0MB)
MaxMetaspaceSize = 17592186044415 MB
G1HeapRegionSize = 0 (0.0MB)
2.5jhat:虚拟机堆存储分析工具
生成http页面,我们后续使用其他工具分析,因为在服务器上面生成一个类型http://localhost:7000的分析页面比较不切合实际。
2.6jstack:Java堆栈跟踪工具
生成此时此刻的线程快照,为了定位线程长时间停顿原因、线程死锁、死循环、请求外部资源等待导致的长时间停顿的原因。
jstack命名格式:jstack [options] vmid
选项 | 作用 |
---|---|
-F | 当正常的请求不被响应时候,强制输出线程堆栈 |
-I | 显示关于锁的附加信息 |
-m | 如果调用的是c,可以打印c/c++堆栈 |
实际用法:我们在调用线程的时候,有一个getAllstackTraces()方法,可以一样输出StackTraceElement对象。
2.7JDK可视化工具
2.7.1JConsole:Java监视与管理控制台
package com.ycy.java.jconsole;
import java.util.ArrayList;
import java.util.List;
/**
* @Copyright © 2017 . All rights reserved. Created with IntelliJ IDEA.
* @project: untitled
* @Package: com.ycy.java.jconsole
* @Description: -Xms100M -Xmx100M
* @autho: ycy
* @Date: 2017-11-01
* @Time: 23:22
*/
public class OOMObject {
public byte[] placeholder=new byte[64*1024];
public static void fillHeal(int num) throws InterruptedException {
List<OOMObject> list=new ArrayList<>();
for (int i=0;i<num;i++) {
//延迟设置
Thread.sleep(50);
list.add(new OOMObject());
}
}
public static void main(String[] args) throws InterruptedException {
fillHeal(1000);
System.gc();
System.out.println(1);
}
}
结果:
2.7.2 死锁实例
/**
* 线程死循环演示
*/
public static void createBusyThread(){
Thread thread=new Thread(new Runnable() {
@Override
public void run() {
while (true){
//34行
}
}
},"testBusyThread");
thread.start();
}
static class SynAddRunable implements Runnable{
Integer a,b;
public SynAddRunable(Integer a,Integer b){
this.a=a;
this.b=b;
}
@Override
public void run() {
synchronized (a){
synchronized (b){
System.out.println(a+b);
}
}
}
}
public static void main(String[] args) throws InterruptedException {
//#内存变化
// fillHeal(1000);
// System.gc();
// System.out.println(1);
//#线程死循环
// createBusyThread();
//死锁代码
for (int i = 0; i <100 ; i++) {
new Thread(new SynAddRunable(1,2)).start();
new Thread(new SynAddRunable(2,1)).start();
}
}
结果