package leak; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandleProxies; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; /* Licensed under the Apache License, Version 2.0 */ public class StackTraceFiller { public static void fill(Throwable throwable) { //containerOnlyFill(abort); bootclassLoaderOnlyFill(throwable); try { Thread.sleep(1000); } catch(InterruptedException ignored) { } throwable.printStackTrace(); } public static void containerOnlyFill(Throwable throwable) { final Throwable[] throwableArray = new Throwable[] { throwable }; try { Runnable target = new Runnable() { @Override public void run() { throwableArray[0].fillInStackTrace(); } }; Thread thread = new Thread(target); thread.start(); thread.join(); } catch(InterruptedException e) { e.printStackTrace(); } finally { throwableArray[0] = null; } } public static void bootclassLoaderOnlyFill(Throwable throwable) { Throwable[] throwableArray = new Throwable[] { throwable }; try { MethodHandles.Lookup lookup = MethodHandles.lookup(); MethodType fillInStackTraceSignature = MethodType.methodType(Throwable.class); MethodHandle fillInStackTraceHandle = lookup.findVirtual(Throwable.class, "fillInStackTrace", fillInStackTraceSignature); MethodHandle arrayGetter = MethodHandles.arrayElementGetter(Throwable[].class); MethodHandle arrayAtZeroGetter = MethodHandles.insertArguments(arrayGetter, 1, 0); MethodHandle arrayAtZeroFillInStackTrace = MethodHandles.filterArguments(fillInStackTraceHandle, 0, arrayAtZeroGetter); MethodHandle noArgFillInStackTrace = MethodHandles.insertArguments(arrayAtZeroFillInStackTrace, 0, (Object) throwableArray); Runnable target = MethodHandleProxies.asInterfaceInstance(Runnable.class, noArgFillInStackTrace); Thread thread = new Thread(target); thread.start(); thread.join(); } catch(NoSuchMethodException | IllegalAccessException | InterruptedException e) { e.printStackTrace(); } finally { throwableArray[0] = null; } } }