diff -r d0eb4fb4bc55 netx/net/sourceforge/swing/SwingUtils.java --- a/netx/net/sourceforge/swing/SwingUtils.java Thu Oct 18 13:09:29 2018 +0200 +++ b/netx/net/sourceforge/swing/SwingUtils.java Thu Oct 18 21:32:37 2018 +0200 @@ -40,6 +40,17 @@ import java.awt.EventQueue; import java.awt.Window; import java.lang.reflect.InvocationTargetException; +/* */ +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; +/* */ import javax.swing.JWindow; import javax.swing.RepaintManager; import javax.swing.SwingUtilities; @@ -49,6 +60,7 @@ /** * Swing / AWT utility class */ + public final class SwingUtils { private static final boolean DEBUG_EDT = System.getProperty("icedtea-web.edt.debug", "false").equalsIgnoreCase("true"); @@ -67,6 +79,51 @@ /* shared Window owner */ private static Window window = null; +/* */ + private static final boolean TRACE_BRIDGE = false; + + private static final boolean ENABLE_EDT_BRIDGE; + + /** single thread pool with max 1 live daemon thread */ + private static final ExecutorService EDT_DAEMON_THREAD_POOL; + + static { + ENABLE_EDT_BRIDGE = System.getProperty("icedtea-web.edt.bridge", "false").equalsIgnoreCase("true"); + if (ENABLE_EDT_BRIDGE) { + trace("Enable EDT Bridge."); + + EDT_DAEMON_THREAD_POOL = new ThreadPoolExecutor(0, 1, + 60L, TimeUnit.SECONDS, + new LinkedBlockingQueue(), + new MainAppContextDaemonThreadFactory() + ); + } else { + EDT_DAEMON_THREAD_POOL = null; + } + } + + private static final class MainAppContextDaemonThreadFactory implements ThreadFactory { + + private final AtomicInteger threadNumber = new AtomicInteger(1); + private final String namePrefix = "itw-edt-thread-"; + + @Override + public Thread newThread(Runnable r) { + final Thread t = new Thread(MAIN_GROUP, r, + namePrefix + threadNumber.getAndIncrement() + ); + if (!t.isDaemon()) { + t.setDaemon(true); + } + if (t.getPriority() != Thread.NORM_PRIORITY) { + t.setPriority(Thread.NORM_PRIORITY); + } + return t; + } + } + +/* */ + private SwingUtils() { // forbidden } @@ -134,6 +191,31 @@ traceWithStack("invokeLater() from EDT: MAY be fixed (useless) ?"); } } +/* */ + else if (ENABLE_EDT_BRIDGE) { + // AppContext bridge + final ClassLoader doRunCL = doRun.getClass().getClassLoader(); + + if (TRACE_BRIDGE) { + trace("invokeLater(doRun): " + + doRun.getClass().getName() + " @ " + + ((doRunCL == null) ? "BootClassLoader" : doRunCL)); + } + + // Ensure bridge is only used by Boot class loader: + if (doRunCL == null) { + EDT_DAEMON_THREAD_POOL.submit(new Runnable() { + @Override + public void run() { + SwingUtilities.invokeLater(doRun); + } + }); + return; + } else { + traceWithStack("SwingUtils.invokeLater() called from external class loader: " + doRunCL); + } + } +/* */ EventQueue.invokeLater(doRun); } @@ -150,6 +232,44 @@ } public static void invokeAndWait(final Runnable doRun) { +/* */ + if (!isMainThreadGroup() && ENABLE_EDT_BRIDGE) { + // AppContext bridge + final ClassLoader doRunCL = doRun.getClass().getClassLoader(); + + if (TRACE_BRIDGE) { + trace("invokeAndWait(doRun): " + + doRun.getClass().getName() + " @ " + + ((doRunCL == null) ? "BootClassLoader" : doRunCL)); + } + + // Ensure bridge is only used by Boot class loader: + if (doRunCL == null) { + final Future future = EDT_DAEMON_THREAD_POOL.submit(new Callable() { + @Override + public Void call() throws Exception { + callOnAppContext(doRun); + return null; + } + }); + try { + // Wait on Future: + future.get(); + } catch (InterruptedException ie) { + OutputController.getLogger().log(OutputController.Level.ERROR_ALL, ie); + } catch (ExecutionException ee) { + if (ee.getCause() != null) { + OutputController.getLogger().log(OutputController.Level.ERROR_ALL, ee.getCause()); + } else { + OutputController.getLogger().log(OutputController.Level.ERROR_ALL, ee); + } + } + return; + } else { + traceWithStack("SwingUtils.invokeAndWait() called from external class loader: " + doRunCL); + } + } +/* */ if (isEventDispatchThread()) { if (TRACE_INVOKE_EDT) { traceWithStack("invokeAndWait() from EDT: to be fixed (illegal) ?");