Exclude jansi classes from metabuild top loader

The launcher embeds a fixed version of jansi above the rest of the
classpath on windows. This causes problems for the scala 2.12 console
because it tries to load methods that don't exist from the old jansi
jar. This can be fixed by excluding all jansi classes from the top
loader.

We also need to exclude jansi classes in the scala instance top class
loader to make the 2.10 console work because scala 2.10 uses a shaded
jline that requires a very old jansi version. Due to the shading, the
thin client doesn't work with the 2.10 console.
This commit is contained in:
Ethan Atkins 2020-11-18 08:12:18 -08:00
parent 1ea0fb7d23
commit 927151485d
2 changed files with 25 additions and 1 deletions

View File

@ -117,6 +117,21 @@ public final class MetaBuildLoader extends URLClassLoader {
if (!foundSBTLoader) topLoader = topLoader.getParent();
}
if (topLoader == null) topLoader = scalaProvider.launcher().topLoader();
// the bundled version of jansi with old versions of the launcher cause
// problems so we need to exclude it from classloading
topLoader =
new ClassLoader(topLoader) {
@Override
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
if (name.startsWith("org.fusesource")) throw new ClassNotFoundException(name);
return super.loadClass(name, resolve);
}
@Override
public String toString() {
return "JansiExclusionClassLoader";
}
};
final TestInterfaceLoader interfaceLoader = new TestInterfaceLoader(interfaceURLs, topLoader);
final JLineLoader jlineLoader = new JLineLoader(jlineURLs, interfaceLoader);

View File

@ -1059,8 +1059,17 @@ object Defaults extends BuildCommon {
classLoaderCache: ClassLoaderCache,
topLoader: ClassLoader,
): ScalaInstance = {
// Scala 2.10 shades jline in the console so we need to make sure that it loads a compatible
// jansi version. Because of the shading, console does not work with the thin client for 2.10.x.
val jansiExclusionLoader = if (version.startsWith("2.10.")) new ClassLoader(topLoader) {
override protected def loadClass(name: String, resolve: Boolean): Class[_] = {
if (name.startsWith("org.fusesource")) throw new ClassNotFoundException(name)
super.loadClass(name, resolve)
}
}
else topLoader
val allJarsDistinct = allJars.distinct
val libraryLoader = classLoaderCache(libraryJars.toList, topLoader)
val libraryLoader = classLoaderCache(libraryJars.toList, jansiExclusionLoader)
val fullLoader = classLoaderCache(allJarsDistinct.toList, libraryLoader)
new ScalaInstance(
version,