From 927151485df60dbf15c506ae4917a85af62afb94 Mon Sep 17 00:00:00 2001 From: Ethan Atkins Date: Wed, 18 Nov 2020 08:12:18 -0800 Subject: [PATCH] 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. --- .../main/java/sbt/internal/MetaBuildLoader.java | 15 +++++++++++++++ main/src/main/scala/sbt/Defaults.scala | 11 ++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/main/src/main/java/sbt/internal/MetaBuildLoader.java b/main/src/main/java/sbt/internal/MetaBuildLoader.java index 08a80aa24..5c83ceed5 100644 --- a/main/src/main/java/sbt/internal/MetaBuildLoader.java +++ b/main/src/main/java/sbt/internal/MetaBuildLoader.java @@ -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); diff --git a/main/src/main/scala/sbt/Defaults.scala b/main/src/main/scala/sbt/Defaults.scala index 8e5ab3f79..c6200785f 100644 --- a/main/src/main/scala/sbt/Defaults.scala +++ b/main/src/main/scala/sbt/Defaults.scala @@ -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,