JVM的几个示例

247 阅读5分钟

一 举个死锁的例子

public class DeadLock {
    public static void main(String[] args) {
       new Thread(A::getA,"ThreadA").start();

       new Thread(B::getB,"ThreadB").start();
    }
}

class A {
    public static synchronized void getA(){
        System.out.println("进入A");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        B.getB();
    }
}

class B {
    public static synchronized void getB(){
        System.out.println("进入B");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        A.getA();
    }
}
类的静态方法是属于类的对象,与类的实例没有关系。
1.jvisualvm

可以点击线程Dump看下。

2.jstack
jstack pid,结果如下
Found one Java-level deadlock:
=============================
"ThreadB":
  waiting to lock monitor 0x00007fa54b8086a8 (object 0x000000076bb588f0, a java.lang.Class),
  which is held by "ThreadA"
"ThreadA":
  waiting to lock monitor 0x00007fa54b808808 (object 0x000000076bdcaf78, a java.lang.Class),
  which is held by "ThreadB"

Java stack information for the threads listed above:
===================================================
"ThreadB":
	at jvm.newjvm.A.getA(DeadLock.java:13)
	- waiting to lock <0x000000076bb588f0> (a java.lang.Class for jvm.newjvm.A)
	at jvm.newjvm.B.getB(DeadLock.java:31)
	- locked <0x000000076bdcaf78> (a java.lang.Class for jvm.newjvm.B)
	at jvm.newjvm.DeadLock$$Lambda$2/1535128843.run(Unknown Source)
	at java.lang.Thread.run(Thread.java:745)
"ThreadA":
	at jvm.newjvm.B.getB(DeadLock.java:25)
	- waiting to lock <0x000000076bdcaf78> (a java.lang.Class for jvm.newjvm.B)
	at jvm.newjvm.A.getA(DeadLock.java:19)
	- locked <0x000000076bb588f0> (a java.lang.Class for jvm.newjvm.A)
	at jvm.newjvm.DeadLock$$Lambda$1/1463801669.run(Unknown Source)
	at java.lang.Thread.run(Thread.java:745)

Found 1 deadlock.
3.jcmd
jcmd 64507 Thread.print
Found one Java-level deadlock:
=============================
"ThreadB":
  waiting to lock monitor 0x00007fa54b8086a8 (object 0x000000076bb588f0, a java.lang.Class),
  which is held by "ThreadA"
"ThreadA":
  waiting to lock monitor 0x00007fa54b808808 (object 0x000000076bdcaf78, a java.lang.Class),
  which is held by "ThreadB"

Java stack information for the threads listed above:
===================================================
"ThreadB":
	at jvm.newjvm.A.getA(DeadLock.java:13)
	- waiting to lock <0x000000076bb588f0> (a java.lang.Class for jvm.newjvm.A)
	at jvm.newjvm.B.getB(DeadLock.java:31)
	- locked <0x000000076bdcaf78> (a java.lang.Class for jvm.newjvm.B)
	at jvm.newjvm.DeadLock$$Lambda$2/1535128843.run(Unknown Source)
	at java.lang.Thread.run(Thread.java:745)
"ThreadA":
	at jvm.newjvm.B.getB(DeadLock.java:25)
	- waiting to lock <0x000000076bdcaf78> (a java.lang.Class for jvm.newjvm.B)
	at jvm.newjvm.A.getA(DeadLock.java:19)
	- locked <0x000000076bb588f0> (a java.lang.Class for jvm.newjvm.A)
	at jvm.newjvm.DeadLock$$Lambda$1/1463801669.run(Unknown Source)
	at java.lang.Thread.run(Thread.java:745)

Found 1 deadlock.
用以上三个工具都可以看出线程死锁的信息。

二 GC垃圾收集过程

代码如下:

        int size = 1024 * 1024;
        Byte[] byte1 = new Byte[2*size];
        Byte[] byte2 = new Byte[2*size];
        Byte[] byte3 = new Byte[2*size];
        Byte[] byte4 = new Byte[2*size];

        System.out.println("hello world!");

设置VM Options 如下:

    -verbose:gc 输出冗余的gc信息
    -Xms20M   堆初始化最小的容量
    -Xmx20M   堆初始化最大的容量
    -Xmn10M   新生代容量
    -XX:+PrintGCDetails
    -XX:SurvivorRatio=8 配置新生代和survivor的大小比例为8:1:1

run下程序的结果如下:

[GC (Allocation Failure) [PSYoungGen: 2238K->867K(9216K)] 10430K->9067K(19456K), 0.0010796 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] 
[GC (Allocation Failure) [PSYoungGen: 867K->851K(9216K)] 9067K->9051K(19456K), 0.0008617 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (Allocation Failure) [PSYoungGen: 851K->0K(9216K)] [ParOldGen: 8200K->8889K(10240K)] 9051K->8889K(19456K), [Metaspace: 3118K->3118K(1056768K)], 0.0133250 secs] [Times: user=0.07 sys=0.00, real=0.02 secs] 
[GC (Allocation Failure) [PSYoungGen: 0K->0K(9216K)] 8889K->8889K(19456K), 0.0004353 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (Allocation Failure) [PSYoungGen: 0K->0K(9216K)] [ParOldGen: 8889K->8873K(10240K)] 8889K->8873K(19456K), [Metaspace: 3118K->3118K(1056768K)], 0.0127611 secs] [Times: user=0.08 sys=0.00, real=0.01 secs] 
Heap
 PSYoungGen      total 9216K, used 410K [0x00000007bf600000, 0x00000007c0000000, 0x00000007c0000000)
  eden space 8192K, 5% used [0x00000007bf600000,0x00000007bf666800,0x00000007bfe00000)
  from space 1024K, 0% used [0x00000007bfe00000,0x00000007bfe00000,0x00000007bff00000)
  to   space 1024K, 0% used [0x00000007bff00000,0x00000007bff00000,0x00000007c0000000)
 ParOldGen       total 10240K, used 8873K [0x00000007bec00000, 0x00000007bf600000, 0x00000007bf600000)
  object space 10240K, 86% used [0x00000007bec00000,0x00000007bf4aa558,0x00000007bf600000)
 Metaspace       used 3194K, capacity 4496K, committed 4864K, reserved 1056768K
  class space    used 348K, capacity 388K, committed 512K, reserved 1048576K
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
	at jvm.newjvm.GCTest1.main(GCTest1.java:16)

先看第一行信息,做第一次Minor垃圾回收。

[GC (Allocation Failure) [PSYoungGen: 2238K->867K(9216K)] 10430K->9067K(19456K), 0.0010796 secs] [Times: user=0.01 sys=0.00, real=0.00 secs]

9216K PSYoungGen 年轻代有9M的可用空间,从2238k回收到867k 已回收空间为1371k。
10430K->9067K(19456K) 19456k为19M的空间可用,堆由于设置了新生代和survivor的大小比例为8:1:1那么新生代有1M的空间是无法使用的。所用总共的空间为19M。

[GC (Allocation Failure) [PSYoungGen: 867K->851K(9216K)] 9067K->9051K(19456K), 0.0008617 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 

第二次垃圾回收。相比第一次并没有回收掉多少空间。可以看到9051k-851k =8200k基本等于8M的空间,基本都在老年代。

[Full GC (Allocation Failure) [PSYoungGen: 851K->0K(9216K)] [ParOldGen: 8200K->8889K(10240K)] 9051K->8889K(19456K), [Metaspace: 3118K->3118K(1056768K)], 0.0133250 secs] [Times: user=0.07 sys=0.00, real=0.02 secs] 

第三次发生一次Full GC。操作完的结果是新生代从851k直接到0,老年代8200到8889,没有回收多大的空间。

[GC (Allocation Failure) [PSYoungGen: 0K->0K(9216K)] 8889K->8889K(19456K), 0.0004353 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (Allocation Failure) [PSYoungGen: 0K->0K(9216K)] [ParOldGen: 8889K->8873K(10240K)] 8889K->8873K(19456K), [Metaspace: 3118K->3118K(1056768K)], 0.0127611 secs] [Times: user=0.08 sys=0.00, real=0.01 secs] 

接下来有发生一次Minor GC,完全没什么变化。 再发生一次Full GC,变化也不太大。