Java以编程方式强制进行线程转储 - 例如“jstack -F -l <​​pid>”</pid>

时间:2015-02-26 14:21:41

标签: java unix dump programmatically-created jstack

我正在尝试以编程方式执行强制java线程转储,就像命令jstack -F -l <PID>一样。

我最好的尝试: 我创建了一个sun.jvm.hotspot.tools.JStack覆盖run()的子类,其代码类似于sun.jvm.hotspot.tools.JStack.run(),但在最后一行调用start(printstream)而不是start()

    StackTrace stacktrace = new StackTrace(mixedMode, concurrentLocks);

    try {
        Class<?> stacktraceTool = stacktrace.getClass().getSuperclass();

        Method stacktraceSetAgent = stacktraceTool.getDeclaredMethod("setAgent", new Class<?>[] { BugSpotAgent.class });
        stacktraceSetAgent.setAccessible(true);
        stacktraceSetAgent.invoke(stacktrace, new Object[] { this.getAgent() });

        Method stacktraceSetDebugeeType = stacktraceTool.getDeclaredMethod("setDebugeeType", new Class<?>[] { int.class });
        stacktraceSetDebugeeType.setAccessible(true);
        stacktraceSetDebugeeType.invoke(stacktrace, new Object[] { this.getDebugeeType() });

        stacktrace.run(new PrintStream(this.targetFile));
    }
    catch (Exception e) {
        e.printStackTrace(System.err);
    }

问题:java.lang.RuntimeException: Attempt to initialize VM twice

因此我做了:

//reset stuff
VM.shutdown();

//clear observer list
Field f = VM.class.getDeclaredField("vmInitializedObservers");
f.setAccessible(true);
VM vmm = VM.getVM();
Object fo = f.get(vmm);
List folist = (List) fo;
folist.clear();

f = sun.jvm.hotspot.runtime.Threads.class.getDeclaredField("threadFactory");
f.setAccessible(true);
f.set(null, null);
f = sun.jvm.hotspot.runtime.Threads.class.getDeclaredField("threadListField");
f.setAccessible(true);
f.setAccessible(true);
f.set(null, null);
f = sun.jvm.hotspot.runtime.Threads.class.getDeclaredField("virtualConstructor");
f.setAccessible(true);
f.set(null, null);
f = sun.jvm.hotspot.runtime.Threads.class.getDeclaredField("access");
f.setAccessible(true);
f.set(null, null);

//reinit observer list
VM.registerVMInitializedObserver(new Observer() {
    public void update(Observable o, Object data) {
        try {
            Method initm = Threads.class.getDeclaredMethod("initialize", new Class<?>[] { TypeDataBase.class });
            initm.invoke(null, new Object[] { VM.getVM().getTypeDataBase() });
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
});

但结果是:

java.lang.RuntimeException: Unable to deduce type of thread from address 0xa5d12400 (expected type JavaThread, CompilerThread, ServiceThread, JvmtiAgentThread, or SurrogateLockerThread) at sun.jvm.hotspot.runtime.Threads.createJavaThreadWrapper(Threads.java:152) at sun.jvm.hotspot.runtime.Threads.first(Threads.java:140) at sun.jvm.hotspot.runtime.DeadlockDetector.createThreadTable(DeadlockDetector.java:149) at sun.jvm.hotspot.runtime.DeadlockDetector.print(DeadlockDetector.java:56) at sun.jvm.hotspot.runtime.DeadlockDetector.print(DeadlockDetector.java:39) at sun.jvm.hotspot.tools.StackTrace.run(StackTrace.java:52) at de.chili.savelogfiles.ChiliJStack.run(ChiliJStack.java:40) at sun.jvm.hotspot.tools.Tool.start(Tool.java:221) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:601) at de.chili.savelogfiles.JStackFRunnable.run(JStackFRunnable.java:81) at java.lang.Thread.run(Thread.java:722) Caused by: sun.jvm.hotspot.types.WrongTypeException: No suitable match for type of address 0xa5d12400 (nearest symbol is _ZTV10JavaThread) at sun.jvm.hotspot.runtime.InstanceConstructor.newWrongTypeException(InstanceConstructor.java:62) at sun.jvm.hotspot.runtime.VirtualConstructor.instantiateWrapperFor(VirtualConstructor.java:80) at sun.jvm.hotspot.runtime.Threads.createJavaThreadWrapper(Threads.java:148) ... 13 more sun.jvm.hotspot.utilities.AssertionFailure: Expecting GenCollectedHeap, G1CollectedHeap, or ParallelScavengeHeap, but got sun.jvm.hotspot.gc_interface.CollectedHeap

我没有想法......

1 个答案:

答案 0 :(得分:1)

我在http://crunchify.com/how-to-generate-java-thread-dump-programmatically

找到了一些有用的东西

可能这有帮助,不知道PID和线程ID是否相同。

 final ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
 final ThreadInfo[] threadInfos = threadMXBean.getThreadInfo(<thread Ids>, 100);