我试图做一个强制Java线程转储编程,就像命令jstack -F -l <PID>
会做。
我最好的尝试:我从sun.jvm.hotspot.tools.JStack
创build了一个子类,使用类似于sun.jvm.hotspot.tools.JStack.run()
代码覆盖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
我出于想法….
我在这里找到了一些有用的东西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);