8

We are currently using Java Compiler 11 and deploy our main artifacts to Java 11. No problem here.

Unfortunately, a service we use only supports Java 8 so we compile some of them targetting Java 8. No problem here.

Our issue is that developers might reference methods that are not available at runtime in Java 8. E.g. List.of(), Optional::stream, etc. javac version 11 will compile it to Java 8, but an exception will be thrown when executed on JVM version 8.

The later is easy enough to identify with a simple grep statement, but the latter is trickier and involves understanding the code/AST.

I checked the docs for Checkstyle, Spotbugs and PMD with no success. IntelliJ is actually very good at this, but it cannot be integrated into our CI pipeline.

And we got this naive/simplistic grep statement:

grep --recursive --extended-regexp '[ \(](List|Set|Map).of' 'our_project'

We would like to have an accurate way to identify incompatible API.

  • Have you tried looking on IntelliJ? I know they have some open source projects and maybe, just maybe, they have the analyzer as a standalone library? – Silviu Burcea Jun 10 '19 at 18:32
  • Also, I think there are some Maven plugins that solves your problem, but I don't know them from top of my head, gotta search for them. – Silviu Burcea Jun 10 '19 at 18:32
  • 1
    Safest solution is to compile Java 8 code with JDK 8 if possible – Michal Kordas Jun 11 '19 at 10:41
  • Perhaps I'm misunderstanding the issue here, but isn't your problem resolved simply [by specifying the `-source` parameter to **javac**](https://docs.oracle.com/en/java/javase/11/tools/javac.html#GUID-AEEC9F07-CB49-4E96-8BC7-BCC2C7F725C9)? That is, specify **-source 8** or **-source 11** when you compile your code? Why use _grep_ or any of those utilities when the Java compiler will do exactly what you want? (i.e. Fail to compile code to be run on Java 8 if it uses API features introduced after Java 8). All the major IDEs let you specify the value of **-source** when you build your code. – skomisa Jul 28 '19 at 01:46
  • @skomisa the issue is that `-source 8` compiles fine since the source code is syntactically compatible with Java 8. Then if you execute the class(es) with *jdk-8 it will fail because `List.of()` (for example), does not exist. `--release 8` is the solution. – Jean-Martin Archer Jul 30 '19 at 05:29
  • @Jean-MartinArcher OK. I was misunderstanding exactly what the source parameter does. Thanks for the clarification. – skomisa Aug 11 '19 at 17:22

1 Answers1

2

Before Java 9, you'd need to use either the Animal Sniffer Plugin or configure the correct -bootclasspath for javac (Under Cross-Compilation-Options on javac) along with the -target option or just use the exact same JDK version.

Since Java 9, there is a new command line option, which solves this problem: --release. Just use e.g. --release 8 to compile for Java8 and javac should fail with a compilation error, if you use any API, that is only available in a later version.

adangel
  • 1,816
  • 14
  • 17
  • That's exactly what we needed. Thanks! ``` javac Test.java --release 8 Test.java:7: error: cannot find symbol List.of(); ^ symbol: method of() location: interface List 1 error ``` – Jean-Martin Archer Jul 30 '19 at 05:30