mirror of
https://github.com/corda/corda.git
synced 2025-01-19 11:16:54 +00:00
add avian.trace.port property
Setting this property (e.g. -Davian.trace.port=5555) will cause the VM to start an extra daemon thread which listens on the specified TCP port for incoming connections and dumps stack traces for all running threads to that socket. You can retrieve that dump using e.g. netcat: nc localhost 5555
This commit is contained in:
parent
3c44cdc50b
commit
ff19ab6c13
61
classpath/avian/Traces.java
Normal file
61
classpath/avian/Traces.java
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
package avian;
|
||||||
|
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.channels.ServerSocketChannel;
|
||||||
|
import java.nio.channels.SocketChannel;
|
||||||
|
|
||||||
|
public class Traces {
|
||||||
|
private static final String Newline = System.getProperty("line.separator");
|
||||||
|
|
||||||
|
private static String traceAllThreads() {
|
||||||
|
StringBuilder buffer = new StringBuilder();
|
||||||
|
|
||||||
|
Thread[] threads = new Thread[Thread.activeCount()];
|
||||||
|
|
||||||
|
int count = Thread.enumerate(threads);
|
||||||
|
for (int i = 0; i < count; ++i) {
|
||||||
|
traceThread(threads[i], buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String traceThread(Thread thread) {
|
||||||
|
StringBuilder buffer = new StringBuilder();
|
||||||
|
|
||||||
|
traceThread(thread, buffer);
|
||||||
|
|
||||||
|
return buffer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void traceThread(Thread thread, StringBuilder buffer) {
|
||||||
|
buffer.append(thread).append(Newline);
|
||||||
|
for (StackTraceElement e: thread.getStackTrace()) {
|
||||||
|
buffer.append("\tat ").append(e).append(Newline);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void startTraceListener(final String host, final int port) {
|
||||||
|
Thread t = new Thread(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
ServerSocketChannel server = ServerSocketChannel.open();
|
||||||
|
server.socket().bind(new InetSocketAddress(host, port));
|
||||||
|
while (true) {
|
||||||
|
SocketChannel c = server.accept();
|
||||||
|
try {
|
||||||
|
c.write(ByteBuffer.wrap(traceAllThreads().getBytes()));
|
||||||
|
} finally {
|
||||||
|
c.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
t.setDaemon(true);
|
||||||
|
t.start();
|
||||||
|
}
|
||||||
|
}
|
1
makefile
1
makefile
@ -1233,6 +1233,7 @@ ifneq ($(classpath),avian)
|
|||||||
$(classpath-src)/avian/Singleton.java \
|
$(classpath-src)/avian/Singleton.java \
|
||||||
$(classpath-src)/avian/Stream.java \
|
$(classpath-src)/avian/Stream.java \
|
||||||
$(classpath-src)/avian/SystemClassLoader.java \
|
$(classpath-src)/avian/SystemClassLoader.java \
|
||||||
|
$(classpath-src)/avian/Traces.java \
|
||||||
$(classpath-src)/avian/VMClass.java \
|
$(classpath-src)/avian/VMClass.java \
|
||||||
$(classpath-src)/avian/VMField.java \
|
$(classpath-src)/avian/VMField.java \
|
||||||
$(classpath-src)/avian/VMMethod.java \
|
$(classpath-src)/avian/VMMethod.java \
|
||||||
|
@ -3533,6 +3533,18 @@ boot(Thread* t, uintptr_t*)
|
|||||||
|
|
||||||
t->m->classpath->boot(t);
|
t->m->classpath->boot(t);
|
||||||
|
|
||||||
|
const char* port = findProperty(t, "avian.trace.port");
|
||||||
|
if (port) {
|
||||||
|
object host = makeString(t, "0.0.0.0");
|
||||||
|
PROTECT(t, host);
|
||||||
|
|
||||||
|
object method = resolveMethod
|
||||||
|
(t, root(t, Machine::BootLoader), "avian/Traces", "startTraceListener",
|
||||||
|
"(Ljava/lang/String;I)V");
|
||||||
|
|
||||||
|
t->m->processor->invoke(t, method, 0, host, atoi(port));
|
||||||
|
}
|
||||||
|
|
||||||
enter(t, Thread::IdleState);
|
enter(t, Thread::IdleState);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
Loading…
Reference in New Issue
Block a user