bug icon indicating copy to clipboard operation
bug copied to clipboard

REPL :javap disallowed by module system on JDK 16

Open lrytz opened this issue 3 years ago • 7 comments

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

scala> :javap scala.Some
java.lang.IllegalAccessException: class scala.tools.nsc.interpreter.shell.JavapTask cannot access class com.sun.tools.javap.JavapFileManager (in module jdk.jdeps) because module jdk.jdeps does not export com.sun.tools.javap to unnamed module @324e4822
	at java.base/jdk.internal.reflect.Reflection.newIllegalAccessException(Reflection.java:385)
	at java.base/java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:687)
	at java.base/java.lang.reflect.Method.invoke(Method.java:559)
	at scala.tools.nsc.interpreter.shell.JavapTask.<init>(JavapClass.scala:498)

From what I understand, the complication is that we need to make javap read a class from the repl's in-memory representation / class loader.

It seems the only accessible API is ToolProvider which only has a run method. I assume we cannot make it search classes in a custom class loader through this.

Personally, I'd be fine throwing out :javap in favor of :asmp which would be easy to implement

scala> :power
Power mode enabled. :phase is at typer.
import scala.tools.nsc._, intp.global._, definitions._
Try :help or completions for vals._ and power._

scala> class HalloVelo
class HalloVelo

scala> scala.tools.nsc.backend.jvm.AsmUtils.traceClass(intp.classLoader.classBytes("HalloVelo"))
Bytecode for class $line31/$read$$iw$HalloVelo
// class version 52.0 (52)
// access flags 0x21
public class $line31/$read$$iw$HalloVelo {

  // compiled from: <console>

  ATTRIBUTE Scala : unknown

  ATTRIBUTE ScalaInlineInfo : unknown
  // access flags 0x1
  public INNERCLASS $line31/$read$$iw $line31/$read $iw
  // access flags 0x1
  public INNERCLASS $line31/$read$$iw$HalloVelo $line31/$read$$iw HalloVelo

  // access flags 0x1011
  public final synthetic L$line31/$read$$iw; $outer

  // access flags 0x1001
  public synthetic $line31$$read$$iw$HalloVelo$$$outer()L$line31/$read$$iw;
   L0
    LINENUMBER 1 L0
    ALOAD 0
    GETFIELD $line31/$read$$iw$HalloVelo.$outer : L$line31/$read$$iw;
    ARETURN
   L1
    LOCALVARIABLE this L$line31/$read$$iw$HalloVelo; L0 L1 0
    MAXSTACK = 1
    MAXLOCALS = 1

  // access flags 0x1
  public <init>(L$line31/$read$$iw;)V
    // parameter final synthetic  $outer
   L0
    LINENUMBER 1 L0
    ALOAD 1
    IFNONNULL L1
    ACONST_NULL
    ATHROW
   L1
   FRAME SAME
    ALOAD 0
    ALOAD 1
    PUTFIELD $line31/$read$$iw$HalloVelo.$outer : L$line31/$read$$iw;
    ALOAD 0
    INVOKESPECIAL java/lang/Object.<init> ()V
    RETURN
   L2
    LOCALVARIABLE this L$line31/$read$$iw$HalloVelo; L0 L2 0
    LOCALVARIABLE $outer L$line31/$read$$iw; L0 L2 1
    MAXSTACK = 2
    MAXLOCALS = 2
}

lrytz avatar Apr 22 '21 07:04 lrytz

Agreed! Wanted this a long time.

som-snytt avatar Apr 22 '21 07:04 som-snytt

I guess Scala 2 doesn't make use of the Java module system. For inside thoughts, see these articles :

michelou avatar Apr 22 '21 08:04 michelou

:asmp sounds like it would be also be easier to port over to Scala 3 than :javap.

harpocrates avatar Jun 24 '21 13:06 harpocrates

Personally, I'd be fine throwing out :javap in favor of :asmp which would be easy to implement

It seems that asm does not rely on JDK classes, So our solution to this problem is to give up javap and add asmp command?

jxnu-liguobin avatar Jul 28 '21 09:07 jxnu-liguobin

or both. scala 2 repl has a classloader issue that requires -nobootcp, so there may be the same issue with scala 3. I like the idea of having many tools in the tool belt.

som-snytt avatar Jul 28 '21 10:07 som-snytt

I will refer to dotty to implement asmp for scala2. Any interested volunteers can pick it up before I submit pr.

jxnu-liguobin avatar Sep 18 '21 09:09 jxnu-liguobin

For reference until we have a lasting answer for the Scala 2 REPL, @retronym pointed out the escape hatch for the module access on a previous tromp down this lane, still an applicable workaround in JDK 17: https://github.com/scala/scala/pull/8400#issuecomment-530211100

$ scala -nobootcp -J--add-exports=jdk.jdeps/com.sun.tools.javap=ALL-UNNAMED

which could be set in JAVA_OPTS more persistently.

ches avatar Oct 15 '21 14:10 ches

here's the Scala-CLI form of the workaround:

scala-cli repl -S 2 -J --add-exports=jdk.jdeps/com.sun.tools.javap=ALL-UNNAMED

(-nobootcp doesn't seem to be necessary? :shrug:)

SethTisue avatar Sep 16 '23 14:09 SethTisue

The "workaround" for -nobootcp mentioned in the error message:

scala -Dscala.repl.info -Xsource:3 -J--add-exports -Jjdk.jdeps/com.sun.tools.javap=ALL-UNNAMED -Yrepl-outdir myreplout -toolcp myreplout

in other words

➜  snips scala -Dscala.repl.info -Xsource:3 -J--add-exports -Jjdk.jdeps/com.sun.tools.javap=ALL-UNNAMED
[info] started at Sat Sep 16 10:39:25 PDT 2023
Welcome to Scala 2.13.12 (OpenJDK 64-Bit Server VM, Java 20.0.2).
Type in expressions for evaluation. Or try :help.

scala 2.13.12> class C
class C

scala 2.13.12> :javap C
On JDK 9 or higher, use -nobootcp to enable :javap, or set -Yrepl-outdir to a file system path on the tool class path with -toolcp.

scala 2.13.12>
:quit
➜  snips scala -Dscala.repl.info -Xsource:3 -J--add-exports -Jjdk.jdeps/com.sun.tools.javap=ALL-UNNAMED -Yrepl-outdir myreplout -toolcp myreplout
[info] started at Sat Sep 16 10:39:50 PDT 2023
Welcome to Scala 2.13.12 (OpenJDK 64-Bit Server VM, Java 20.0.2).
Type in expressions for evaluation. Or try :help.

scala 2.13.12> class C
class C

scala 2.13.12> :javap -public C
Compiled from "<console>"
public class C {
  public final $iw $outer;
  public $iw C$$$outer();
  public C($iw);
}

scala 2.13.12>

where myreplout is a real directory mentioned by both options.

I don't know if there is a use case where it's not feasible to use -nobootcp, such that this mode is necessary.

I see that :paste -raw class output goes directly under -Yrepl-outdir. But I also see :paste -java output is only virtual.

som-snytt avatar Sep 16 '23 17:09 som-snytt