private static void resetGlobalStateInLoggers() { LogManager.getLogManager().reset(); withGlobalStaticField("java.util.logging.Level$KnownLevel", "nameToLevels", NativeImageBuildServer::removeImageLoggers); withGlobalStaticField("java.util.logging.Level$KnownLevel", "intToLevels", NativeImageBuildServer::removeImageLoggers); }
private static void resetGlobalStateInGraal() { withGlobalStaticField("org.graalvm.compiler.nodes.NamedLocationIdentity$DB", "map", f -> ((EconomicSet<?>) f.get(null)).clear()); withGlobalStaticField("org.graalvm.compiler.debug.DebugContext$Immutable", "CACHE", f -> { Object[] cache = (Object[]) f.get(null); for (int i = 0; i < cache.length; i++) { cache[i] = null; } }); }
private static void resetResourceBundle() { withGlobalStaticField("java.util.ResourceBundle", "cacheList", list -> ((ConcurrentHashMap<?, ?>) list.get(null)).clear()); }
private static int withJVMContext(PrintStream out, PrintStream err, Supplier<Integer> body) { Properties previousProperties = (Properties) System.getProperties().clone(); PrintStream previousOut = System.out; PrintStream previousErr = System.err; System.setOut(out); System.setErr(err); ResourceBundle.clearCache(); try { return body.get(); } catch (Throwable t) { t.printStackTrace(); throw t; } finally { System.setProperties(previousProperties); System.setOut(previousOut); System.setErr(previousErr); resetGlobalStateInLoggers(); resetResourceBundle(); resetGlobalStateInGraal(); withGlobalStaticField("java.lang.ApplicationShutdownHooks", "hooks", f -> { @SuppressWarnings("unchecked") IdentityHashMap<Thread, Thread> hooks = (IdentityHashMap<Thread, Thread>) f.get(null); hooks.forEach((x, y) -> { x.setContextClassLoader(NativeImageBuildServer.class.getClassLoader()); y.setContextClassLoader(NativeImageBuildServer.class.getClassLoader()); }); }); } }
private NativeImageBuildServer(int port, PrintStream logOutput) { this.port = port; this.logOutput = logOutput; threadPoolExecutor = new ThreadPoolExecutor(SERVER_THREAD_POOL_SIZE, SERVER_THREAD_POOL_SIZE, Long.MAX_VALUE, TimeUnit.DAYS, new LinkedBlockingQueue<>()); /* * Set the right classloader in the process reaper */ withGlobalStaticField("java.lang.UNIXProcess", "processReaperExecutor", f -> { ThreadPoolExecutor executor = (ThreadPoolExecutor) f.get(null); final ThreadFactory factory = executor.getThreadFactory(); executor.setThreadFactory(r -> { Thread t = factory.newThread(r); t.setContextClassLoader(NativeImageBuildServer.class.getClassLoader()); return t; }); }); System.setProperty("java.util.concurrent.ForkJoinPool.common.threadFactory", NativeImageThreadFactory.class.getName()); /* initialize the default fork join pool with the application loader */ if (ForkJoinPool.commonPool().getFactory().getClass() != NativeImageThreadFactory.class) { throw VMError.shouldNotReachHere("Wrong thread pool factory: " + ForkJoinPool.commonPool().getFactory().getClass()); } }