'. '

Frgaal

From APIDesign

Revision as of 12:57, 22 April 2022 by JaroslavTulach (Talk | contribs)
Jump to: navigation, search

I love Frgaal and you'll love it too: Wouldn't it be great to have the latest Java language features available on your old JDK? As old as JDK8? Frgaal allows you to do it. There is a Maven plugin, integration with Gradle, a way to use it from command line... read more at http://frgaal.org


Can I use Frgaal via ToolProvider API?

Given following code (that invokes the JavaCompiler via ToolProvider for a custom CODE snippet that uses JDK17 Record:

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
 
class ModernJavaCompiler {
  private static final String CODE = "record R (String name) {}";
 
  public static void main(String... args) throws Exception {
      JavaCompiler compiler = javax.tools.ToolProvider.getSystemJavaCompiler();
      List<String> itrbl = Arrays.asList("-source", "17", "-target", "8");
      List<String> itrbl1 = null;
      List<JavaFileObject> itrbl2 = Collections.singletonList(new Src(CODE));
      JavaCompiler.CompilationTask task = compiler.getTask(null, null, null, itrbl, itrbl1, itrbl2);
      Boolean res = task.call();
      if (!Boolean.TRUE.equals(res)) {
          throw new IllegalStateException("Compilation failed: " + res);
      } else {
          System.out.println("Compiled OK");
      }
  }
 
  static class Src extends SimpleJavaFileObject {
        private final String code;
 
        public Src(String code) throws URISyntaxException {
            super(new URI("memory://Code.java"), Kind.SOURCE);
            this.code = code;
        }
 
        @Override
        public String getName() {
            return "Code.java";
        }
 
 
        @Override
        public CharSequence getCharContent(boolean bln) throws IOException {
            return code;
        }
  }
}

This is a Java class that can be compiled using

javac -source 8 -target 8 ModernJavaCompiler.java

Then it can be executed on JDK-17 as

$ /jdk-17/bin/java ModernJavaCompiler
Compiled OK

However executing the same code on JDK-11 is going to fail (as the Javac from JDK-11 doesn't support -source 17):

$ /jdk11/bin/java ModernJavaCompiler
Exception in thread "main" java.lang.IllegalArgumentException: error: invalid source release: 17
    at jdk.compiler/com.sun.tools.javac.main.Arguments.error(Arguments.java:907)
    at jdk.compiler/com.sun.tools.javac.main.Arguments.doProcessArgs(Arguments.java:383)
    at jdk.compiler/com.sun.tools.javac.main.Arguments.processArgs(Arguments.java:347)
    at jdk.compiler/com.sun.tools.javac.main.Arguments.init(Arguments.java:246)
    at jdk.compiler/com.sun.tools.javac.api.JavacTool.getTask(JavacTool.java:185)
    at jdk.compiler/com.sun.tools.javac.api.JavacTool.getTask(JavacTool.java:119)
    at jdk.compiler/com.sun.tools.javac.api.JavacTool.getTask(JavacTool.java:68)
    at ModernJavaCompiler.main(ModernJavaCompiler.java:23)

The idea would be to replace the standard "compiler tool" with one coming from the frgaal. Let's try to disable the regular compiler first. There is an option --limit-modules in JDK-11+ and the idea is to use it to use it to disable standard JavaC:

$ /jdk11/bin/java --limit-modules java.base ModernJavaCompiler
Exception in thread "main" java.lang.NoClassDefFoundError: javax/tools/ToolProvider

Great! The disabling works. The "compiler tool" is completely missing. Now there is a time to inject Frgaal instead. Following script shows how to get it all working:

$ mkdir -p META-INF/services
$ echo com.sun.tools.javac.api.JavacTool > META-INF/services/javax.tools.JavaCompiler
$ curl -o compiler.jar https://repo1.maven.org/maven2/org/frgaal/compiler/18.0.0/compiler-18.0.0.jar
$ /jdk-11/bin/java --limit-modules java.base,jdk.zipfs -cp compiler.jar:. ModernJavaCompiler
warning: [options] system modules path not set in conjunction with -source 17
warning: No output directory specified, cannot perform multi-release compilation
2 warnings
Compiled OK

E.g. it is necessary to provide extra ServiceLoader registration in META-INF/services path on the class path, but then it seems to run. Embed Frgaal into your own programs and use the latest Java features on any JDK!

Personal tools
buy