java - VisualVM 线程转储与堆转储不匹配?

标签 java jvm visualvm jstack

我写了一个死锁示例代码,然后用VisualVM分析它,发现导致死锁的对象,线程转储和堆转储的地址不同。

示例代码是:

package com.example.chapter4;

/**
 * @author Cnfn
 * @date 2017/11/05
 */
public class ThreadDeadlock {
    static class SyncAddRunnable implements Runnable {
        int a, b;

        public SyncAddRunnable(int a, int b) {
            this.a = a;
            this.b = b;
        }

        @Override
        public void run() {
            synchronized (Integer.valueOf(a)) {
                synchronized (Integer.valueOf(b)) {
                    System.out.println(a + b);
                }
            }
        }
    }

    public static void main(String[] args) {
        for (int i = 0; i < 100; ++i) {
            new Thread(new SyncAddRunnable(1, 2)).start();
            new Thread(new SyncAddRunnable(2, 1)).start();
        }
    }
}

然后运行示例代码,Integer.valueOf(1)Integer.valueOf(2)会导致死锁。但是线程转储和堆转储之间的这些地址是不同的。

线程转储:

threaddump

堆转储:

heapdump

但是jstack命令结果与堆转储匹配:

jstack

那么,为什么 VisualVM 的线程转储与堆转储不匹配?为什么jstack结果与VisualVM的堆转储匹配?

或者,我有什么问题吗?

谢谢~~~

PS:我再次执行程序,并将应用程序快照、堆转储、线程转储和jstack日志上传到Google Drive

最佳答案

转储中的对象 ID 是该对象在 Java 堆中的地址。

GC 可以在堆上移动对象。地址已更改的事实意味着在运行 jstack 和使用 VisualVM 进行线程转储之间存在 GC。

关于java - VisualVM 线程转储与堆转储不匹配?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47119542/

相关文章:

java - Thread.start() 不调用 Thread.run() 方法

java - 在 Java VisualVM 中添加远程 VM

java - Checkstyle 在最终变量的命名约定上与普通 Java 不同?

java - @DeclareRoles 如何定义特定角色中的用户?

java - 不抛出 VirtualMachineError 保证

java - 无法通过 SSH 隧道远程调试 JVM

java - 在线java编译器如何工作?

java - VisualVM 堆大小不遵循已用大小

java - jvisualvm:卡在 “Loading Heap Dump...” 屏幕上

java - NoClassDefFoundError与gradle,giraph和hadoop