Skip to content

Instantly share code, notes, and snippets.

@Col-E
Last active October 31, 2024 08:03
Show Gist options
  • Save Col-E/8a8f9bb135007cadaf849f99674327af to your computer and use it in GitHub Desktop.
Save Col-E/8a8f9bb135007cadaf849f99674327af to your computer and use it in GitHub Desktop.
Stack printing System.exit(int) values
// Authors: xdark, Col-E
AccessPatcher.patch();
MethodHandles.Lookup lookup = LookupUtil.lookup();
Runnable hook = () -> {
try {
Class<?> stackFrameClass = Class.forName("java.lang.LiveStackFrame");
MethodHandle getLocals = lookup.findVirtual(stackFrameClass, "getLocals", MethodType.methodType(Object[].class))
.asType(MethodType.methodType(Object[].class, Object.class));
Method getStackWalker = stackFrameClass.getDeclaredMethod("getStackWalker", Set.class);
getStackWalker.setAccessible(true);
StackWalker stackWalker = (StackWalker) getStackWalker.invoke(null, Set.of(StackWalker.Option.RETAIN_CLASS_REFERENCE, StackWalker.Option.SHOW_HIDDEN_FRAMES));
stackWalker.forEach(frame -> {
try {
if (frame.getDeclaringClass() == System.class && frame.getMethodName().equals("exit")) {
Object[] locals = (Object[]) getLocals.invoke(frame);
// Value is stored as a long with for some reason (which messes with negative values), so map back to int.
String local0 = locals[0].toString().replaceAll("\\D+", "");
int exit = (int) Long.parseLong(local0);
System.err.println("The exit code was: " + exit);
}
} catch (Throwable t) {
throw new RuntimeException(t);
}
});
} catch (Throwable t) {
t.printStackTrace();
logger.error("Failed to create stack-walker");
}
};
try {
// We use this instead of the Runtime shutdown hook thread because this will run on the same thread
// as the call to System.exit(N)
Class<?> shutdown = lookup.findClass("java.lang.Shutdown");
MethodHandle add = lookup.findStatic(shutdown, "add", MethodType.methodType(void.class, int.class, boolean.class, Runnable.class));
add.invoke(9, false, hook); // the int param is 'slot' which can be 0-9 (but 0-3 are already occupied)
} catch (Throwable t) {
t.printStackTrace();
logger.error("Failed to add shutdown hook");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment