diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2016-12-12 15:33:02 +1000 |
---|---|---|
committer | Jason Zaugg <jzaugg@gmail.com> | 2016-12-12 15:33:02 +1000 |
commit | a346b779324a474a180b1370fddc5a58ff629410 (patch) | |
tree | ecac6c1da900a9d59aa2e046315d3b89a093f563 /src/repl/scala/tools/nsc | |
parent | 3de1c0c56ee530f4e75533fc9e1909fe0cde31b5 (diff) | |
download | scala-a346b779324a474a180b1370fddc5a58ff629410.tar.gz scala-a346b779324a474a180b1370fddc5a58ff629410.tar.bz2 scala-a346b779324a474a180b1370fddc5a58ff629410.zip |
Support extra module references in the REPL
By default, scala-compiler.jar is in the bootclasspath, which gives us a
`null` when we call `classOf[IMain].getClassLoader`. That value is used
as the parent class loader of the classloader that evals code in the REPL.
Under JDK9, this breaks lookup of classes on the module path:
```
scala -J--add-modules=java.compiler -J--add-exports=jdk.jdeps/com.sun.tools.javap=ALL-UNNAMED
Welcome to Scala 2.12.1 (Java HotSpot(TM) 64-Bit Server VM, Java 9-ea).
Type in expressions for evaluation. Or try :help.
scala> new com.sun.tools.javap.JavapTask();
java.lang.NoClassDefFoundError: com/sun/tools/javap/JavapTask
at java.base/java.lang.Class.getDeclaredMethods0(Native Method)
at java.base/java.lang.Class.privateGetDeclaredMethods(Class.java:2948)
```
A workaround is to use `-nobootcp`.
This commit uses the system classloader as the parent in place of the null classloader
to make this work in both cases.
```
qscala -J--add-modules=java.compiler -J--add-exports=jdk.jdeps/com.sun.tools.javap=ALL-UNNAMED
Welcome to Scala 2.12.2-20161208-165912-3de1c0c (Java HotSpot(TM) 64-Bit Server VM, Java 9-ea).
Type in expressions for evaluation. Or try :help.
scala> new com.sun.tools.javap.JavapTask();
res0: com.sun.tools.javap.JavapTask = com.sun.tools.javap.JavapTask@1f1cddf3
scala>
```
Note that the `:javap` command still requires `-nobootcp` because code in the REPL implements
an interface in a the `java.compiler` module.
Diffstat (limited to 'src/repl/scala/tools/nsc')
-rw-r--r-- | src/repl/scala/tools/nsc/interpreter/ILoop.scala | 6 | ||||
-rw-r--r-- | src/repl/scala/tools/nsc/interpreter/IMain.scala | 6 |
2 files changed, 8 insertions, 4 deletions
diff --git a/src/repl/scala/tools/nsc/interpreter/ILoop.scala b/src/repl/scala/tools/nsc/interpreter/ILoop.scala index 0dd96b2616..d1096fda4e 100644 --- a/src/repl/scala/tools/nsc/interpreter/ILoop.scala +++ b/src/repl/scala/tools/nsc/interpreter/ILoop.scala @@ -105,8 +105,10 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) } class ILoopInterpreter extends IMain(settings, out) { - override protected def parentClassLoader = - settings.explicitParentLoader.getOrElse( classOf[ILoop].getClassLoader ) + override protected def parentClassLoader = { + val replClassLoader = classOf[ILoop].getClassLoader // might be null if we're on the boot classpath + settings.explicitParentLoader.orElse(Option(replClassLoader)).getOrElse(ClassLoader.getSystemClassLoader) + } } /** Create a new interpreter. */ diff --git a/src/repl/scala/tools/nsc/interpreter/IMain.scala b/src/repl/scala/tools/nsc/interpreter/IMain.scala index 99acc34811..980d12f9b8 100644 --- a/src/repl/scala/tools/nsc/interpreter/IMain.scala +++ b/src/repl/scala/tools/nsc/interpreter/IMain.scala @@ -255,8 +255,10 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends } /** Parent classloader. Overridable. */ - protected def parentClassLoader: ClassLoader = - settings.explicitParentLoader.getOrElse( this.getClass.getClassLoader() ) + protected def parentClassLoader: ClassLoader = { + val replClassLoader = this.getClass.getClassLoader() // might be null if we're on the boot classpath + settings.explicitParentLoader.orElse(Option(replClassLoader)).getOrElse(ClassLoader.getSystemClassLoader) + } /* A single class loader is used for all commands interpreted by this Interpreter. It would also be possible to create a new class loader for each command |