TNG/remote-executor-gradle-plugin — pull request #1 by kohsuke (2013-06-23 14:44:00+00:00)
Title: Fixed class loader constraint violation

See https://groups.google.com/forum/#!topic/jenkinsci-dev/D760HwlorrY for more details. Quoting,

-----
Gradle sets up a classloader hierarchy in such a way that there's one CL that loads all the plugins (I'll call this PCL), then there's another classloader that masks all but the publicly exposed APIs of the PCL (I'll call this MCL), then the classloader that loads stuff in buildSrc (I'll call this BCL.)

JUnitTestClassExecuter is in PCL, and this is visible to BCL as MCL does not hide this. JUnitTestClassExecuter refers to a number of JUnit classes in its signature, but those JUnit classes are masked by MCL, so they are NOT visible to BCL.

Now, because JUnit classes can't go through MCL, our BCL loads its own set of JUnit classes based on buildSrc/build.gradle dependency declaration.

So this creates a situation: if you are in BCL, the JUnit classes you see comes from BCL, but you also see JUnitTestClassExecuter from PCL, and the JUnit classes JUnitTestClassExecuter is seeing is visible from BCL. This constitutes the class loader constraint violation.

In other words, this has nothing to do with remoting. In fact, you can reproduce the same problem if you execute RuntimeExceptionCallable locally inside Gradle.

The reason it worked with CLI upgrade is because Jenkins has its own copy of JUnit, and when PCL and BCL are remoted, they'll both delegate (parent first) to the Jenkins' uberClassloader, and therefore we'll back to the single copy of JUnit.

To properly fix this, the fix needs to come from Gradle --- for example by checking the transitive reference closure visibility in BCL at the development time --- but that'd take too long for us, so I'm going to provide a mechanism to let us load JUnit jars into the application classloader (ACL).

This would force both BCL and PCL to load JUnit from ACL, eliminating the constraint violation.