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:
Joel Dice 2013-03-08 14:47:27 -07:00
parent 3c44cdc50b
commit ff19ab6c13
3 changed files with 74 additions and 0 deletions

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

View File

@ -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 \

View File

@ -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;