3

I want to load a Java version specific JavaCompiler.

This is how I take compiler instance currently:

JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();

My aim is to compile a "user Java code" according to the Java version (Java 8 or Java 13) in which it is originally written.

I am building my whole source code in Java 8.

Hence compiler instance that I am getting will be Java 8 specific and I can not compile Java 13 code (correct me if I am wrong).

I have both Java 8 and Java 13 installed.

I read below statement from this article

The ToolProvider locates the default compiler in this case. It is also possible to locate alternative compilers or tools by using service provider mechanism.

Is there any way from which I can load Java version specific Java compiler? Is there a workaround for it?

Or, if I build project using Java 13, can I then compile version-specific using --target or --source or --release arguments of Java 13 compiler?

Lii
  • 11,553
  • 8
  • 64
  • 88
niranjan_harpale
  • 2,048
  • 1
  • 17
  • 21
  • Have you tried [getSourceVersions](https://docs.oracle.com/javase/8/docs/api/javax/tools/Tool.html#getSourceVersions--) from Java 13 to see what versions the `JavaCompiler` supports? I don't know, but maybe if you just build your project using 13 then all previous versions will be supported, as is usually the case with compilers (to my knowledge). – gthanop Apr 03 '20 at 11:57
  • actually, I have a project built in java 8, so I get only java 8 release and less with getSourcecVersions. Yes, maybe with java 13 build I can do. **BUT** I am aiming to get a compiler of java 13 from a project built with java 8. I will be trying with java 13 built. – niranjan_harpale Apr 03 '20 at 12:09
  • Looks to me like you could extend class `ToolProvider` and override method `getSystemToolClassLoader()` - which was deprecated in JDK9, by the way - to return your custom class loader that loads the appropriate classes to perform the required compilation level. Of-course it is much easier to go backwards, i.e. you can compile Java 8 code with a Java 13 compiler, out of the box, as they say. – Abra Apr 03 '20 at 12:42
  • 2
    You don’t need to build your project using Java 13, the relevant point is on which version you *run* your code which uses the `JavaCompiler`. – Holger Apr 03 '20 at 13:24
  • @Abra, Thanks for the suggestion, can you provide me little code implementation about how exactly I can do this? – niranjan_harpale Apr 03 '20 at 13:27
  • @Holger I run my code with Java 8, but I want the compiler to compile java 13 code, and also java 8 code. (maybe without changing the build version). – niranjan_harpale Apr 03 '20 at 13:29
  • 2
    Then, you need a Java 8 compatible compiler implementation that supports compiling Java 13 code. The implementation shipped with JDK 8 doesn’t. – Holger Apr 03 '20 at 13:34
  • Your code may be compiled with JDK *n* and run with any JRE *m* (where *m≥n*). Thus your runtime may not have any available compiler... Also read https://stackoverflow.com/questions/1293308/java-api-to-find-out-the-jdk-version-a-class-file-is-compiled-for – Jean-Baptiste Yunès Apr 04 '20 at 07:38
  • 1
    The Eclipse compiler `ecj` still runs on Java 8 and latest builds support compiling Java versions 1.3 ... 14. – Stephan Herrmann Apr 04 '20 at 09:51

2 Answers2

2

So the final approach I used is:

Step 1:

Install both Java 8 and Java 13.

Step 2:

Make Java 13 default

both javac and java

Step 3:

Build the project in Java 13

Step 4:

Use Java 13 compiler to compile both Java 8 and Java 13 programs.

JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();

It will give you Java 13 compiler.

Step 5:

While compilation I used the --release option.

You have to specify

--release 13 for Java 13 (or u don't have too, as the compiler is Java 13 only)

and

--release 8 for Java 8.

Step 6: For executing the class files:

java 8 execution path for java 8 execution.

for ex:

path_to_java_8/java Helloworld

For Java 13 execution you can directly use java command as java 13 is default

java Helloworld
niranjan_harpale
  • 2,048
  • 1
  • 17
  • 21
1

I haven't tried this, but the following snippet might get you going:

JavaCompiler eclipseCompiler = ServiceLoader.load(org.eclipse.jdt.internal.compiler.tool.EclipseCompiler.class).iterator().next();

To build your application you just need to add the following to your depedencies (given as maven coordinates):

<groupId>org.eclipse.jdt</groupId>
<artifactId>ecj</artifactId>
<version>3.21.0</version>

This will run on Java 8 and allows your application to compile for compliance 13.

Stephan Herrmann
  • 7,963
  • 2
  • 27
  • 38