Skip to content

Inconsistent behavior of -release (JEP 247) #13015

Open
@szeiger

Description

@szeiger

Given these equivalent Scala and Java sources, and compilers running on JDK 17:

$ cat Main.scala
import jdk.jfr.internal.Repository
class Main {}

$ cat Main.java
import jdk.jfr.internal.Repository;
public class Main {}

$ java -version
java version "17.0.11" 2024-04-16 LTS
Java(TM) SE Runtime Environment Oracle GraalVM 17.0.11+7.1 (build 17.0.11+7-LTS-jvmci-23.0-b34)
Java HotSpot(TM) 64-Bit Server VM Oracle GraalVM 17.0.11+7.1 (build 17.0.11+7-LTS-jvmci-23.0-b34, mixed mode, sharing)

javac does not allow the use of the the internal API, with or without an explicit --release 17 because it always limits access based on modules:

$ javac  Main.java
Main.java:1: error: package jdk.jfr.internal is not visible
import jdk.jfr.internal.Repository;
              ^
  (package jdk.jfr.internal is declared in module jdk.jfr, which does not export it)
1 error

$ javac --release 17  Main.java
Main.java:1: error: package jdk.jfr.internal is not visible
import jdk.jfr.internal.Repository;
              ^
  (package jdk.jfr.internal is declared in module jdk.jfr, which does not export it)
1 error

Without --release the module can be made accessible with --add-exports but this is rejected when used with --release (whether the requested version matches the current JDK version or not):

$ javac --add-exports=jdk.jfr/jdk.jfr.internal=ALL-UNNAMED Main.java

$ javac --release 17 --add-exports=jdk.jfr/jdk.jfr.internal=ALL-UNNAMED Main.java
error: exporting a package from system module jdk.jfr is not allowed with --release
1 error

$ javac --release 11 --add-exports=jdk.jfr/jdk.jfr.internal=ALL-UNNAMED Main.java
error: exporting a package from system module jdk.jfr is not allowed with --release
1 error

Instead of using --release it is possible to manually set both -source and -target version and override the system module path (the module equivalent of the bootclasspath) to get the same effect as --release while allowing the use of --add-exports:

$ javac -source 11 -target 11  --system /Users/stefan.zeiger/.sdkman/candidates/java/11-zulu-local Main.java --add-exports=jdk.jfr/jdk.jfr.internal=ALL-UNNAMED

scalac has several inconsistencies with this scheme:

  • By default scalac is not module-aware. It allows access to private APIs without warnings or errors:

    $ scalac Main.scala
    
  • Setting an explicit release version enforces module access but only if the version is lower than the current JDK version, otherwise it is treated the same as not using modules:

    $ scalac -release:17 Main.scala
    
    $ scalac -release:11 Main.scala
    Main.scala:1: error: object internal is not a member of package jdk.jfr
    import jdk.jfr.internal.Repository
                   ^
    1 error
    
  • There are no equivalents of --add-exports and --system and thus no way to target an older release without enforcing strict module access.

(This is about Scala 2; I tested it with 2.13.14 but AFAICT there are no changes in this area in any recent 2.13 or 2.12 version since the feature was added; I have not tried it with Scala 3)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions