Class loading: Instance of loaded class can't load classes which can be loaded by the classloader

See https://gist.github.com/sherter/30906735f115a85b85df#file-classloading-groovy for test cases that demonstrate the problem.

When resolving dependencies and using a URLClassLoader to load classes from those dependencies, an instance of a loaded class complains about not being able to find a certain other class. However, when using the URLClassLoader directly, the class is available.
It is not a problem with the loaded class, since everything works fine when using a GradleRunner instead of a ProjectBuilder test fixture.

This could also be a problem with the Spock testing framework…

The test passes if you set the parent classloader as null for the classloader you are creating.

def classLoader = new URLClassLoader(urls as URL[], (ClassLoader)null)

The default parent classloader is the user system classloader which contains the classpath passed to the JVM.
In this case, it contains the Gradle runtime classpath, which contains a lot of dependencies. The Gradle runtime classpath seems to be added by the gradleApi dependency. It might be the guava library that is also part of Gradle runtime dependencies that is causing the classloading problem.

That’s it, adding configurations { compile gradleApi() } in the second test makes it fail as well. Thanks!

One should always use a dedicated ClassLoader with no parent in a plugin then, I guess?!

I’m not sure if you can make that a generic rule. I think custom classloaders should be avoided in plugins if it’s possible.

The issue described is basically GRADLE-1715. In the past I did implement custom classloaders in some of my plugins to work around this problem. It’s messy.