diff --git a/src/main/java/hudson/remoting/UserRequest.java b/src/main/java/hudson/remoting/UserRequest.java index ff898c2d2..26ef41cba 100644 --- a/src/main/java/hudson/remoting/UserRequest.java +++ b/src/main/java/hudson/remoting/UserRequest.java @@ -34,6 +34,8 @@ import java.io.Serializable; import java.io.NotSerializableException; import java.io.ObjectInputStream; +import java.util.logging.Level; +import java.util.logging.Logger; /** * {@link Request} that can take {@link Callable} whose actual implementation @@ -86,10 +88,40 @@ public UserRequest(Channel local, Callable c) throws IOException { return result; } + private static boolean workaroundDone = false; protected UserResponse perform(Channel channel) throws EXC { try { ClassLoader cl = channel.importedClassLoaders.get(classLoaderProxy); + // Allow forcibly load of a class, allows to workaround: + // @See https://issues.jenkins-ci.org/browse/JENKINS-19445 + // @Related https://issues.tmatesoft.com/issue/SGT-451 + final String clazz = System.getProperty(RemoteClassLoader.class.getName() + ".force", null); + if ( clazz != null && !workaroundDone) { + // Optimistic logging set. + String eventMsg = "Loaded"; + Level logLevel = Level.INFO; + // java.lang classes can only be instantiated by the bootstrap Classloader. + // Guarantees that *all* threads with whatever Classloader in use, have the + // same mutex instance: an intance of java.lang.Class + synchronized(java.lang.Object.class) + { + workaroundDone = true; + try { + final Class loaded = Class.forName( clazz, true, cl ); + } catch (final ClassNotFoundException cnfe) { + // not big deal, elevate log to warning and swallow exception + eventMsg = "Couldn't find"; + logLevel = Level.WARNING; + } + } + final Logger logger = Logger.getLogger(RemoteClassLoader.class.getName()); + if( logger.isLoggable(logLevel) ) + { + logger.log(logLevel, "%s class '%s' using classloader: %s", new String[]{ eventMsg, clazz, cl.toString()} ); + } + } + RSP r = null; Channel oldc = Channel.setCurrent(channel); try {