Java forced thread dump programmatically - like “jstack -F -l <PID>”

天大地大妈咪最大 提交于 2020-01-02 17:24:29

问题


I am trying to do a forced java thread dump programmatically, just like the command jstack -F -l <PID> would do it.

My best attempt: I created a subclass from sun.jvm.hotspot.tools.JStack overwriting run() with the following code analogous to sun.jvm.hotspot.tools.JStack.run() but in the last line calling start(printstream) instead of 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);
    }

The problem: java.lang.RuntimeException: Attempt to initialize VM twice

Therefore I did:

//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();
        }
    }
});

But this results in:

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

Im out of ideas....


回答1:


I found some thing useful here http://crunchify.com/how-to-generate-java-thread-dump-programmatically

May be this can help, dont know if PID and thread ids are same.

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


来源:https://stackoverflow.com/questions/28744850/java-forced-thread-dump-programmatically-like-jstack-f-l-pid

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!