Closed
Description
Overview
This issue was discovered in conjunction with tests on Java 9; however, the issue is likely applicable on Java 8 as well.
The following pseudo-code, when run inside a Java 9 JShell session...
println("ServiceLoader.load(TestEngine.class)");
println(" loader = " + Thread.currentThread().getContextClassLoader());
ServiceLoader.load(TestEngine.class).forEach(System.out::println);
println("ServiceLoader.load(TestEngine.class, getClass().getClassLoader())");
println(" loader = " + getClass().getClassLoader());
ServiceLoader.load(TestEngine.class, getClass().getClassLoader()).forEach(System.out::println);
println("ServiceLoader.load(TestEngine.class, TestEngine.class.getClassLoader())");
println(" loader = " + TestEngine.class.getClassLoader());
ServiceLoader.load(TestEngine.class, TestEngine.class.getClassLoader()).forEach(System.out::println);
yields the following :
ServiceLoader.load(TestEngine.class)
loader = jdk.jshell.execution.DefaultLoaderDelegate$RemoteClassLoader@4b952a2d
-
ServiceLoader.load(TestEngine.class, getClass().getClassLoader())
loader = jdk.internal.loader.Loader@42607a4f
* org.junit.jupiter.engine.JupiterTestEngine@fa36558
* org.junit.vintage.engine.VintageTestEngine@672872e1
ServiceLoader.load(TestEngine.class, TestEngine.class.getClassLoader())
loader = jdk.internal.loader.Loader@42607a4f
* org.junit.jupiter.engine.JupiterTestEngine@484970b0
* org.junit.vintage.engine.VintageTestEngine@4470f8a6
The problem leads to org.junit.platform.commons.util.PreconditionViolationException: Cannot create Launcher without at least one TestEngine; consider adding an engine implementation JAR to the classpath
messages and was first encountered at forax/pro#23 (comment)
Work-around
- A work-around is to use
getClass().getClassLoader()
as the result ofClassLoaderUtils.getDefaultClassLoader()
. - The user (tool) has to set context classloader to the one that contains the engines: External Java command line tool "launcher" feature forax/pro#23 (comment)
Deliverables
- Investigate a safer/better way to load available engines (and other objects) at runtime.