jcm
jcm

Reputation: 5659

Confused by Java and Scala interop

I'm a little confused by how Scala and Java interact. For example, I am building a Play application which is using version 2.11.6 of Scala, and I need an object to represent a date.

Ideally, I would like to use LocalDate from Java 8, but is this possible if Scala 2.11 targets Java JDK 6?

I would like to get a better understanding of how different versions of Java work with Scala and how the two are related.

Upvotes: 1

Views: 469

Answers (2)

badcook
badcook

Reputation: 3739

To answer your specific question, if you run scalac with JDK8, then yes you can use LocalDate with Scala 2.11.

As for the more general question, there's four basic ways Scala and Java interact that are decoupled from each other version-wise (at least in theory).

  • At compile time, some version of java must be running scalac
  • At compile time, scalac reads some version of JVM bytecode
  • At compile time, scalac emits some version of JVM bytecode
  • At run time, java (via the scala script) runs the JVM bytecode scalac emitted.

So let's see how this stacks up for Scala 2.10.5's scalac, Scala 2.11.x's scalac, and the upcoming Scala 2.12.x's scalac and Java 6, 7, and 8.

  • Scala 2.10.5:
    • scalac can be run by Java 6, 7, or 8 (due to java's backwards compatibility)
    • scalac can read Java 6 or 7 bytecode
    • scalac emits Java 6 (default), or 7 (optional) bytecode for the Scala-specific parts but if it reads Java 7 bytecode (e.g. because you're using a Java 7 library), then your final product will have Java 7 bytecode in it as well which is called by Java 6 bytecode.
    • Depending on your behavior in your previous step you will either have pure Java 6 bytecode which can then be run by Java 6, 7, or 8's java or bytecode with Java 7-specific features which can then only be run by Java 7 or 8's java.
  • Scala 2.11.x:
    • scalac can be run by Java 6, 7, or 8
    • scalac can read Java 6, 7, or 8 bytecode (depending on the version x of 2.11.x more or fewer Java 8 bytecode features can be read and used)
    • scalac emits Java 6 (default), or Java 7 (optional) bytecode
    • Same story as 2.10.5 here
  • Scala 2.12.x:
    • scalac can only be run by Java 8
    • scalac can read Java 8 bytecode and 7 bytecode by virtue of Java's backwards compatibility (I'm not sure about the story here whether scalac makes any additional effort to be more backwards compatible than Java 8's java is, e.g. for Java 6 compatibility)
    • scalac emits Java 8 bytecode
    • Java 8's java must be used to run the resulting binary

Just to emphasize that in theory these steps are completely decoupled, Scala 2.12's scalac could hypothetically be compiled by Scala 2.11's scalac to result in a scalac which can be run by Java 6, but whose resulting output could only be run by a Java 8 java.

In the case of Scala 2.11, you can use Java 8, as long as you provide those classes to scalac. The only special thing about LocalDate is that it is bundled with the Java Platform so you implicitly get access to it if you run scalac with Java 8 and don't if you run scalac with Java 6 or 7. If you are using a third-party Java 8 library, you could provide the compiled JAR to a Scala 2.11.x scalac to use regardless of which Java version is running scalac. That bytecode though may find its way into your own emitted JAR, which can complicate things for downstream users.

This means for any non-purely Scala project, you must let your consumers know both the Scala version and Java version you used for any JARs you generate. If your project is a library, and your consumer uses a compatible Scala version but an incompatible Java version, her/his code may compile, but will not run.

Upvotes: 3

cchantep
cchantep

Reputation: 9168

Scala version and Java version are distinct: you can run the same Scala version (let say 2.10.5) on different Java versions (e.g. 1.6, 1.7, 1.8).

But if you use JSE types which are specific to a JVM version, your Scala code won't run with a previous Java version. As if you build your Scala app/lib with a provided dependency, without having the runtime actually providing it.

Moreover, if the bytecode generated, by scalac according the configured Java version, is more recent than the one of the JRE (compiled in Java 8 but executed with JRE 1.6), it cannot be interpreted, as any plain Java code.

Upvotes: 0

Related Questions