scala / bug

Scala 2 bug reports only. Please, no questions — proper bug reports only.
https://scala-lang.org
232 stars 21 forks source link

Scala ClassLoader breaks nio FileSystemProvider API #10247

Open scabug opened 7 years ago

scabug commented 7 years ago

java.nio.file.spi.FileSystemProvider loads implementations using ClassLoader.getSystemClassLoader().

However, Scala uses a system ClassLoader that doesn't search among JARs on the classpath, resulting in it being impossible to use custom FileSystemProvider implementations.

As an example, try running the google-cloud-nio example; here is a gist showing shell cmds and output.

When the same example JAR is run with java -cp … and scala -cp …, the former finds the custom FileSystemProvider (gs scheme) but the latter doesn't.

I'm currently planning to use this workaround to call FileSystemProvider.loadInstalledProviders while the system classloader is temporarily overwritten to Thread.currentThread().getContextClassLoader, which properly finds FileSystemProvider implementations in user-supplied JARs.

This SO provides basically the same analysis and diagnosis.

scabug commented 7 years ago

Imported From: https://issues.scala-lang.org/browse/SI-10247?orig=1 Reporter: Ryan Williams (rdub) Affected Versions: 2.11.8, 2.12.1

som-snytt commented 7 years ago

Using scala -toolcp path makes your app jar available to the system class loader.

Or, use the API where you can provide the class loader to find providers which are not "installed."

This example shows loading a test provider from a build dir.

$ skala -toolcp ~/bin
Welcome to Scala 2.12.2 (OpenJDK 64-Bit Server VM 1.8.0_112)

scala> import java.nio.file.spi.FileSystemProvider
import java.nio.file.spi.FileSystemProvider

scala> FileSystemProvider.installedProviders
res0: java.util.List[java.nio.file.spi.FileSystemProvider] = [sun.nio.fs.LinuxFileSystemProvider@12abdfb, com.acme.FlakeyFileSystemProvider@b0e5507, com.acme.FlakeyTPDFileSystemProvider@6bbe50c9, com.sun.nio.zipfs.ZipFileSystemProvider@3c46dcbe]

scala> :quit

Or specifying loader:

$ skala -cp ~/bin
Welcome to Scala 2.12.2 (OpenJDK 64-Bit Server VM 1.8.0_112)

scala> import java.net.URI
import java.net.URI

scala> val uri = URI.create("tpd:///?count=10000")
uri: java.net.URI = tpd:///?count=10000

scala> import collection.JavaConverters._
import collection.JavaConverters._

scala> val em = Map.empty[String, AnyRef].asJava
em: java.util.Map[String,AnyRef] = {}

scala> import java.nio.file.FileSystems
import java.nio.file.FileSystems

scala> FileSystems.
getDefault   getFileSystem   newFileSystem

scala> FileSystems.newFileSystem(uri, em, $intp.classLoader)
res1: java.nio.file.FileSystem = com.acme.FlakeyFileSystemProvider$FlakeyFileSystem@2553dcc0
ryan-williams commented 7 years ago

Thanks for these workarounds, @som-snytt!

Unfortunately I'm not sure that either one works very well for me:

Can we also have some conversation about why Scala doesn't have this Just Work? I assume there is no Good Reason for it, but rather that it's an unfortunate side-effect of something well under the hood of what most Scala users know or care to know about… is there any hope of "fixing" this?

som-snytt commented 7 years ago

That's a good question. Maybe there's a good reason for Spark to update its script. You can "install" Scala in the ext/lib directory of your Java installation, along with your jars, IIRC. It's been a long time since I resorted to that.

ryan-williams commented 7 years ago

That's a good question. Maybe there's a good reason for Spark to update its script.

Not sure I follow; is using -toolcp better than -cp in general, or would Spark and downstream libraries be using -toolcp just to work around this issue with the Scala classloader?

I assume the latter, which seems like a non-starter to me, at least until we get a straight answer about why Scala is doing this and what fixing the problem at its source would entail.

You can "install" Scala in the ext/lib directory of your Java installation, along with your jars, IIRC.

Sorry, I'm missing what this is supposed to solve or why.

Per the above, I'd like to discuss why Scala is doing this and what it would take to fix it, though I appreciate the thorough exploration of the space of possible work-arounds 😎.

som-snytt commented 7 years ago

You can drop your filesystem.jar in ext/lib and it will be visible to the system class loader. I think that's what "installed" means. But I don't think you're interested in doing that.

I just spent some time refreshing my understanding: basically, you're saying that invoking the runner script with scala -classpath my.jar:. MyMain should put my.jar on the java classpath. Right now, the arguments to java are switched around, so the command is java MainGenericRunner -classpath my.jar:..

Just guessing, but that might be because the same script is used for both scala and scalac.

Here's an issue: https://github.com/lampepfl/dotty/issues/44

In 2.13, they want more flexible module handling, and also use the Java 9 modules, so now might be a good time to start or join a conversation on their discussion site, or mention it on gitter. In fact, I'll go mention it now.

To reiterate, this isn't an issue with ScalaClassLoader, just with the scala script that assembles the java command that runs your program.

The confusing options are -nobootcp and -Dscala.usejavacp=false. Only -toolcp gets your jar on the system class path, i.e., java's -classpath.

You could also consider using -Djava.system.class.loader but again, if you're not able to set -toolcp then that is out of scope for you. I do suspect that the alternative API, where you supply the classloader, is the most correct and robust.

SethTisue commented 6 years ago

@som-snytt should this issue be closed? the combination of "out of scope" yet remaining open is confusing

som-snytt commented 6 years ago

@SethTisue I always confuse "out of scope" with "out of rope."

I'll try to confirm that I said something correct in the thread and whether the request that it just work can be met. The class loader fix happened since then.

ryan-williams commented 6 years ago

As an update, I've been using a wrapper around nio.Path that hooks into Path construction, checks whether some FileSystem/classpath-munging has occurred to work around this issue, and does the FileSystem/classpath-munging if not (involving reflection to modify private java stdlib global vars 😔); relevant docs.

That got me unblocked, but I don't think a world where [everyone who wants to use JSR203 libraries from Scala] has to [use my library or roll their own similar library] is desirable.

I'm also a little confused that this hasn't come up more widely / there aren't others mentioning that they've run into this; I thought folks I work with in the ADAM universe (cf. linked issue above) would have, but perhaps they and everyone else primarily use the analogous HDFS FileSystem APIs (that JSR203 was meant to mimic/replace, IIUC)?

Anyway, I'll defer to y'all about what level of fixing, further documenting recommended workarounds, #wontfix'ing, etc. is the right outcome here, thanks.

gourlaysama commented 6 years ago

I think this is more of a Spark problem (and/or bad design in the JDK):

I'm also a little confused that this hasn't come up more widely / there aren't others mentioning that they've run into this

I suppose it is because people don't use the scala launcher script in production. You end up packaging your app/service/whatever, and what you use to do that (sbt-native-packager for example) generates a launcher script for your thing that looks like:

java [-Xms, -Xmx, ...] -cp [~full classpath, including scala & your fs~] YourMainClass

And that will make everything work just fine. I don't want the scala script on my server anyway, it comes with the compiler, repl, ... and those don't belong there.

(As for the dev experience, in sbt you need to enable forking when running/testing, and then everything works the same. It is annoying that it doesn't Just Work™ in the REPL though.)

I have no idea how Spark does all this, or if they allow users to easily inject stuff onto the classpath of Spark itself, but that's what you would need.

som-snytt commented 6 years ago

I do use REPL scripting on my server, so it should just work. Right now it looks pretty broken. With the need for Java 9 support, it's a good time to revisit what does it think it's doing?

Here's the REPL class loader, which is more precise than -Ylog-classpath.

It wasn't intended to put ./"" on the class path; maybe that suffered in a refactor. There's still a comment in the script about the perils of quoting or losing quotes. And one effect of the war to keep dot off the class path is specifying an empty path.

I did a quick munge of the script that just puts the Scala user -classpath on the Java -classpath. The present use case for service loading just works. Maybe another use case breaks?

I don't know that there is any benefit in the current set-up, where a special class loader takes over. The runner code can still use a ScalaClassLoader that delegates to the app class loader without any loss of ergonomics.

# scala -usebootcp -cp lib/gcs-nio.jar

$ SCALA_RUNNER_DEBUG=true $SCALA_HOME/bin/scala -usebootcp -Dscala.usejavacp=true -cp lib/gcs-nio.jar
saved stty:
4500:5:bf:8a3b:3:1c:7f:15:4:0:1:0:11:13:1a:0:12:f:17:16:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0

/usr/lib/jvm/jdk1.8.0/bin/java
-Xmx256M
-Xms32M
-Dscala.usejavacp=true
-Xbootclasspath/a:/home/amarki/scala-2.12.4/lib/jline-2.14.5.jar:/home/amarki/scala-2.12.4/lib/scala-compiler.jar:/home/amarki/scala-2.12.4/lib/scala-library.jar:/home/amarki/scala-2.12.4/lib/scalap-2.12.4.jar:/home/amarki/scala-2.12.4/lib/scala-parser-combinators_2.12-1.0.6.jar:/home/amarki/scala-2.12.4/lib/scala-reflect.jar:/home/amarki/scala-2.12.4/lib/scala-swing_2.12-2.0.0.jar:/home/amarki/scala-2.12.4/lib/scala-xml_2.12-1.0.6.jar
-classpath
""
-Dscala.boot.class.path=/home/amarki/scala-2.12.4/lib/jline-2.14.5.jar:/home/amarki/scala-2.12.4/lib/scala-compiler.jar:/home/amarki/scala-2.12.4/lib/scala-library.jar:/home/amarki/scala-2.12.4/lib/scalap-2.12.4.jar:/home/amarki/scala-2.12.4/lib/scala-parser-combinators_2.12-1.0.6.jar:/home/amarki/scala-2.12.4/lib/scala-reflect.jar:/home/amarki/scala-2.12.4/lib/scala-swing_2.12-2.0.0.jar:/home/amarki/scala-2.12.4/lib/scala-xml_2.12-1.0.6.jar
-Dscala.home=/home/amarki/scala-2.12.4
-Denv.emacs=
scala.tools.nsc.MainGenericRunner
-Dscala.usejavacp=true
-cp
lib/gcs-nio.jar

# show(getClass.getClassLoader)

scala.tools.nsc.interpreter.IMain$TranslatingClassLoader@5bb3131b of type class scala.tools.nsc.interpreter.IMain$TranslatingClassLoader with classpath [(memory)] and

parent being scala.reflect.internal.util.ScalaClassLoader$URLClassLoader@69b1e8f8 of type class scala.reflect.internal.util.ScalaClassLoader$URLClassLoader with classpath

[file:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/resources.jar,file:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/rt.jar,file:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/jsse.jar,file:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/jce.jar,file:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/charsets.jar,file:/home/amarki/scala-2.12.4/lib/jline-2.14.5.jar,file:/home/amarki/scala-2.12.4/lib/scala-compiler.jar,file:/home/amarki/scala-2.12.4/lib/scala-library.jar,file:/home/amarki/scala-2.12.4/lib/scalap-2.12.4.jar,file:/home/amarki/scala-2.12.4/lib/scala-parser-combinators_2.12-1.0.6.jar,file:/home/amarki/scala-2.12.4/lib/scala-reflect.jar,file:/home/amarki/scala-2.12.4/lib/scala-swing_2.12-2.0.0.jar,file:/home/amarki/scala-2.12.4/lib/scala-xml_2.12-1.0.6.jar,file:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext/dnsns.jar,file:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext/nashorn.jar,file:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext/zipfs.jar,file:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext/icedtea-sound.jar,file:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext/sunjce_provider.jar,file:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext/localedata.jar,file:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext/sunpkcs11.jar,file:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext/sunec.jar,file:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext/cldrdata.jar,file:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext/jaccess.jar,file:/home/amarki/snips/lib/gcs-nio.jar]

and parent being sun.misc.Launcher$AppClassLoader@ed17bee of type class sun.misc.Launcher$AppClassLoader with classpath

[file:/home/amarki/snips/%22%22]

and parent being sun.misc.Launcher$ExtClassLoader@77468bd9 of type class sun.misc.Launcher$ExtClassLoader with classpath

[file:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext/dnsns.jar,file:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext/nashorn.jar,file:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext/zipfs.jar,file:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext/icedtea-sound.jar,file:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext/sunjce_provider.jar,file:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext/localedata.jar,file:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext/sunpkcs11.jar,file:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext/sunec.jar,file:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext/cldrdata.jar,file:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext/jaccess.jar]

and parent being primordial classloader with boot classpath

[/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/resources.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/rt.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/sunrsasign.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/jsse.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/jce.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/charsets.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/jfr.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/classes:/home/amarki/scala-2.12.4/lib/jline-2.14.5.jar:/home/amarki/scala-2.12.4/lib/scala-compiler.jar:/home/amarki/scala-2.12.4/lib/scala-library.jar:/home/amarki/scala-2.12.4/lib/scalap-2.12.4.jar:/home/amarki/scala-2.12.4/lib/scala-parser-combinators_2.12-1.0.6.jar:/home/amarki/scala-2.12.4/lib/scala-reflect.jar:/home/amarki/scala-2.12.4/lib/scala-swing_2.12-2.0.0.jar:/home/amarki/scala-2.12.4/lib/scala-xml_2.12-1.0.6.jar]

with -nobootcp

# scala -nobootcp -cp lib/gcs-nio.jar

$ SCALA_RUNNER_DEBUG=true $SCALA_HOME/bin/scala -nobootcp -Dscala.usejavacp=true -cp lib/gcs-nio.jar
saved stty:
4500:5:bf:8a3b:3:1c:7f:15:4:0:1:0:11:13:1a:0:12:f:17:16:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0

/usr/lib/jvm/jdk1.8.0/bin/java
-Xmx256M
-Xms32M
-Dscala.usejavacp=true
-classpath
/home/amarki/scala-2.12.4/lib/jline-2.14.5.jar:/home/amarki/scala-2.12.4/lib/scala-compiler.jar:/home/amarki/scala-2.12.4/lib/scala-library.jar:/home/amarki/scala-2.12.4/lib/scalap-2.12.4.jar:/home/amarki/scala-2.12.4/lib/scala-parser-combinators_2.12-1.0.6.jar:/home/amarki/scala-2.12.4/lib/scala-reflect.jar:/home/amarki/scala-2.12.4/lib/scala-swing_2.12-2.0.0.jar:/home/amarki/scala-2.12.4/lib/scala-xml_2.12-1.0.6.jar
-Dscala.home=/home/amarki/scala-2.12.4
-Denv.emacs=
scala.tools.nsc.MainGenericRunner
-Dscala.usejavacp=true
-cp
lib/gcs-nio.jar

# show(getClass.getClassLoader)

scala.tools.nsc.interpreter.IMain$TranslatingClassLoader@67b355c8 of type class scala.tools.nsc.interpreter.IMain$TranslatingClassLoader with classpath [(memory)]

and parent being scala.reflect.internal.util.ScalaClassLoader$URLClassLoader@598778cc of type class scala.reflect.internal.util.ScalaClassLoader$URLClassLoader with classpath

[file:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/resources.jar,file:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/rt.jar,file:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/jsse.jar,file:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/jce.jar,file:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/charsets.jar,file:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext/dnsns.jar,file:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext/nashorn.jar,file:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext/zipfs.jar,file:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext/icedtea-sound.jar,file:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext/sunjce_provider.jar,file:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext/localedata.jar,file:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext/sunpkcs11.jar,file:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext/sunec.jar,file:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext/cldrdata.jar,file:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext/jaccess.jar,file:/home/amarki/scala-2.12.4/lib/jline-2.14.5.jar,file:/home/amarki/scala-2.12.4/lib/scala-compiler.jar,file:/home/amarki/scala-2.12.4/lib/scala-library.jar,file:/home/amarki/scala-2.12.4/lib/scalap-2.12.4.jar,file:/home/amarki/scala-2.12.4/lib/scala-parser-combinators_2.12-1.0.6.jar,file:/home/amarki/scala-2.12.4/lib/scala-reflect.jar,file:/home/amarki/scala-2.12.4/lib/scala-swing_2.12-2.0.0.jar,file:/home/amarki/scala-2.12.4/lib/scala-xml_2.12-1.0.6.jar,file:/home/amarki/snips/lib/gcs-nio.jar]

and parent being sun.misc.Launcher$AppClassLoader@74a14482 of type class sun.misc.Launcher$AppClassLoader with classpath

[file:/home/amarki/scala-2.12.4/lib/jline-2.14.5.jar,file:/home/amarki/scala-2.12.4/lib/scala-compiler.jar,file:/home/amarki/scala-2.12.4/lib/scala-library.jar,file:/home/amarki/scala-2.12.4/lib/scalap-2.12.4.jar,file:/home/amarki/scala-2.12.4/lib/scala-parser-combinators_2.12-1.0.6.jar,file:/home/amarki/scala-2.12.4/lib/scala-reflect.jar,file:/home/amarki/scala-2.12.4/lib/scala-swing_2.12-2.0.0.jar,file:/home/amarki/scala-2.12.4/lib/scala-xml_2.12-1.0.6.jar]

and parent being sun.misc.Launcher$ExtClassLoader@5524cca1 of type class sun.misc.Launcher$ExtClassLoader with classpath

[file:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext/dnsns.jar,file:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext/nashorn.jar,file:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext/zipfs.jar,file:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext/icedtea-sound.jar,file:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext/sunjce_provider.jar,file:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext/localedata.jar,file:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext/sunpkcs11.jar,file:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext/sunec.jar,file:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext/cldrdata.jar,file:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext/jaccess.jar]

and parent being primordial classloader with boot classpath

[/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/resources.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/rt.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/sunrsasign.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/jsse.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/jce.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/charsets.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/jfr.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/classes]

Modified:

$ SCALA_RUNNER_DEBUG=true $SCALA_HOME/bin/scala -usebootcp -classpath lib/gcs-nio.jar saved stty:
4500:5:bf:8a3b:3:1c:7f:15:4:0:1:0:11:13:1a:0:12:f:17:16:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0

/usr/lib/jvm/jdk1.8.0/bin/java
-Xmx256M
-Xms32M
-Xbootclasspath/a:/home/amarki/scala-2.12.4/lib/jline-2.14.5.jar:/home/amarki/scala-2.12.4/lib/scala-compiler.jar:/home/amarki/scala-2.12.4/lib/scala-library.jar:/home/amarki/scala-2.12.4/lib/scalap-2.12.4.jar:/home/amarki/scala-2.12.4/lib/scala-parser-combinators_2.12-1.0.6.jar:/home/amarki/scala-2.12.4/lib/scala-reflect.jar:/home/amarki/scala-2.12.4/lib/scala-swing_2.12-2.0.0.jar:/home/amarki/scala-2.12.4/lib/scala-xml_2.12-1.0.6.jar
-classpath
lib/gcs-nio.jar
-Dscala.boot.class.path=/home/amarki/scala-2.12.4/lib/jline-2.14.5.jar:/home/amarki/scala-2.12.4/lib/scala-compiler.jar:/home/amarki/scala-2.12.4/lib/scala-library.jar:/home/amarki/scala-2.12.4/lib/scalap-2.12.4.jar:/home/amarki/scala-2.12.4/lib/scala-parser-combinators_2.12-1.0.6.jar:/home/amarki/scala-2.12.4/lib/scala-reflect.jar:/home/amarki/scala-2.12.4/lib/scala-swing_2.12-2.0.0.jar:/home/amarki/scala-2.12.4/lib/scala-xml_2.12-1.0.6.jar
-Dscala.home=/home/amarki/scala-2.12.4
-Dscala.usejavacp=true
-Denv.emacs=
scala.tools.nsc.MainGenericRunner

Welcome to Scala 2.12.4 (OpenJDK 64-Bit Server VM, Java 1.8.0_151).
Type in expressions for evaluation. Or try :help.

scala> java.nio.file.spi.FileSystemProvider.installedProviders
res0: java.util.List[java.nio.file.spi.FileSystemProvider] = [sun.nio.fs.LinuxFileSystemProvider@31c628e7, com.sun.nio.zipfs.ZipFileSystemProvider@3240b2a4, CloudStorageFileSystemProvider{storage=com.google.cloud.storage.StorageImpl@120d3fd}]
som-snytt commented 6 years ago

I haven't looked at whether sbt supports forking when running the console. Hopefully any wrinkle could be ironed out. Similarly, folks did work for Spark to support adding jars to the compiler class path, so this is a natural use case. Maybe some future REPL will support that in a natural way.

som-snytt commented 4 years ago

There ought to be an issue to make -nobootcp the default for scala. That's necessary now for :javap to work in REPL.