示例程序
public class JVMTools {
private List<Integer> ilist = new LinkedList<>();
private int count = 0;
//synchronized修饰的方法,线程并发执行
private synchronized void operation(){
count++;
//线程休息1秒
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//不断向list中放入Integer对象
ilist.add(count);
System.out.println(Thread.currentThread().getName() + " " + count);
}
public class Counter extends Thread{
@Override
public void run() {
//保证线程永远执行下去
while (true){
operation();
}
}
}
public void counter(){
//启动两条线程
Counter counter1 = new Counter();
Counter counter2 = new Counter();
counter1.start();
counter2.start();
}
//启动示例程序
public static void main(String[] args){
JVMTools tools = new JVMTools();
tools.counter();
//因为程序堆空间增长相对缓慢
//在不调整堆空间大小前提下,强制JVM进行垃圾回收
System.gc();
}
}
执行上面的程序,在命令终端执行下面的命令,可以观察到输出结果。
jps:查看Java进程
jps(JVM Process Status Tool)可以列出正在运行的虚拟机进程,显示虚拟机执行主类名称以及这些进程的本地虚拟机唯一ID(LVMID,Local Virtual Machine Identifier)。
//可以看到我们的示例程序运行的LVMID为33371
jps
运行结果:
33371 JVMTools
jstat:统计信息监视工具
jstat(JVM Statistics Monitoring Tool)用于监视虚拟机各种运行状态信息的命令。
//查看示例程序的垃圾回收信息
jstat -gc 33371
运行结果:
//1000ms统计一次gc情况,一共统计100次
jstat -gcutil 33371 1000 100
运行结果:
增加代码System.gc()后,会观察到出现了一次的Full GC和Young GC。而上图因为没有System.gc()代码执行,Full GC和Young GC均为0。
jmap:查看Java内存镜像
jmap(Memory Map for Java)用于生成堆转储快照。
//查看示例程序的堆中活动的对象以及大小
jmap -histo:live 33371| less
运行结果:
下图中红框标记的就是示例程序中List对象和不断向其中添加的Integer对象。会随着示例程序的不断执行,List对象占用的内存增大。
jstack:Java堆栈跟踪工具
jstack(Stack Trace for Java)用于生成虚拟机当前时刻的线程快照。
//查看示例程序线程状态
jstack 33371
运行结果:
示例程序中,两条线程并发访问临界资源,因此在任一时刻一定都存在一条线程处于阻塞(BLOCKED)状态,另一条线程处于运行,这里因为执行sleep(1000),刚好线程处于有限等待(TIME_WAITING)状态,休眠等待唤醒。线程状态可以参考Java的线程状态。