Skip to content

Using -release option instead of -target can break compilation #12824

Not planned
@eejbyfeldt

Description

@eejbyfeldt

Reproduction steps

Scala version: 2.13.11
Java version: 17.0.7

$ cat import_sun.scala
import sun._
$ scalac -deprecation -target:8 import_sun.scala
warning: -target is deprecated: Use -release instead to compile against the correct platform API.
1 warning
$ scalac -release:8 import_sun.scala
import_sun.scala:1: error: not found: object sun
import sun._
       ^
1 error

Problem

Compiling with the -target flag gives a deprecation warning suggesting to use -release instead. But switching using -release means that the code no longer compiles.

If this is the intended behavior maybe the deprecation warnings/documentation should include more information of the differences between -target and -release.

Activity

lrytz

lrytz commented on Jul 11, 2023

@lrytz
Member

Compiling on JDK 17 with -target:8 is not safe

➜ sandbox cat Test.scala
object Test {
  def main(args: Array[String]): Unit = {
    println(">".indent(2))
  }
}

➜ sandbox java17
➜ sandbox scalac -target:8 Test.scala
warning: 1 deprecation; re-run with -deprecation for details
1 warning
➜ sandbox scala Test
  >

➜ sandbox java8
➜ sandbox scala Test
Exception in thread "main" java.lang.NoSuchMethodError: java.lang.String.indent(I)Ljava/lang/String;
	at Test$.main(Test.scala:3)
	at Test.main(Test.scala)

Using -release instead fixes that

➜ sandbox java17
➜ sandbox scalac -release:8 Test.scala
Test.scala:3: error: value indent is not a member of String
did you mean indexOf or intern?
    println(">".indent(2))
                ^

However, the corresponding classpath element that is used under -release instead of the JDK doesn't contain symbols for private API (such as sun._). So you need to build on JDK 8 in this case.

som-snytt

som-snytt commented on Jul 11, 2023

@som-snytt

Duplicates #12643

The comment at the end of that ticket mentions -javabootclasspath and elsewhere:

To compile against a JDK 8 rt.jar, use -javabootclasspath rt.jar -nobootcp.

eejbyfeldt

eejbyfeldt commented on Jul 11, 2023

@eejbyfeldt
Author

Thanks for clarifying.

Is this expected that using --release 17 using sun.* classes compiles but fails at runtime?

$ cast use_sun.scala
import sun.nio.ch.DirectBuffer

object Test {
  def main(args: Array[String]): Unit = {
    println(classOf[sun.nio.ch.DirectBuffer])
  }
}
$ scalac -release 17 use_sun.scala 
$ scala -release 17 use_sun.scala 
Exception in thread "main" java.lang.IllegalAccessError: class Main$ (in unnamed module @0xe260766) cannot access class sun.nio.ch.DirectBuffer (in module java.base) because module java.base does not export sun.nio.ch to unnamed module @0xe260766
	at Main$.main(use_sun.scala:5)
	at Main.main(use_sun.scala)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at scala.reflect.internal.util.RichClassLoader$.$anonfun$run$extension$1(ScalaClassLoader.scala:101)
	at scala.reflect.internal.util.RichClassLoader$.asContext$extension(ScalaClassLoader.scala:36)
	at scala.reflect.internal.util.RichClassLoader$.run$extension(ScalaClassLoader.scala:101)
	at scala.tools.nsc.CommonRunner.run(ObjectRunner.scala:30)
	at scala.tools.nsc.CommonRunner.run$(ObjectRunner.scala:28)
	at scala.tools.nsc.ObjectRunner$.run(ObjectRunner.scala:45)
	at scala.tools.nsc.CommonRunner.runAndCatch(ObjectRunner.scala:37)
	at scala.tools.nsc.CommonRunner.runAndCatch$(ObjectRunner.scala:36)
	at scala.tools.nsc.ObjectRunner$.runAndCatch(ObjectRunner.scala:45)
	at scala.tools.nsc.AbstractScriptRunner.runCompiled(ScriptRunner.scala:168)
	at scala.tools.nsc.AbstractScriptRunner.$anonfun$runScript$1(ScriptRunner.scala:177)
	at scala.tools.nsc.AbstractScriptRunner.$anonfun$withCompiledScript$9(ScriptRunner.scala:154)
	at scala.tools.nsc.util.package$.trackingThreads(package.scala:55)
	at scala.tools.nsc.util.package$.waitingForThreads(package.scala:32)
	at scala.tools.nsc.AbstractScriptRunner.withCompiledScript(ScriptRunner.scala:151)
	at scala.tools.nsc.AbstractScriptRunner.runScript(ScriptRunner.scala:177)
	at scala.tools.nsc.MainGenericRunner.runTarget$1(MainGenericRunner.scala:75)
	at scala.tools.nsc.MainGenericRunner.run$1(MainGenericRunner.scala:92)
	at scala.tools.nsc.MainGenericRunner.process(MainGenericRunner.scala:105)
	at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:113)
	at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala)
lrytz

lrytz commented on Jul 11, 2023

@lrytz
Member

Yeah, the Scala compiler doesn't do access checks according to the Java module system (scala/scala-dev#529).

https://nipafx.dev/five-command-line-options-hack-java-module-system/ is a good article.

added a commit that references this issue on Sep 13, 2023

[SPARK-45144][BUILD] Downgrade `scala-maven-plugin` to 4.7.1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      Using -release option instead of -target can break compilation · Issue #12824 · scala/bug