Frgaal
From APIDesign
(5 intermediate revisions not shown.) | |||
Line 4: | Line 4: | ||
=== Can I use [[Frgaal]] via {{JDK|javax/tools|ToolProvider}} [[API]]? === | === Can I use [[Frgaal]] via {{JDK|javax/tools|ToolProvider}} [[API]]? === | ||
- | Let's imagine we have a following code | + | Let's imagine we have a following code invoking the {{JDK|javax/tool|JavaCompiler}} via {{JDK|javax/tool|ToolProvider}} for a custom ''CODE'' snippet defining {{JDK|java/lang|Record}} with main method: |
<source lang="java"> | <source lang="java"> | ||
Line 10: | Line 10: | ||
import java.net.URI; | import java.net.URI; | ||
import java.net.URISyntaxException; | import java.net.URISyntaxException; | ||
+ | import java.util.ArrayList; | ||
import java.util.Arrays; | import java.util.Arrays; | ||
import java.util.Collections; | import java.util.Collections; | ||
Line 27: | Line 28: | ||
public static void main(String... args) throws Exception { | public static void main(String... args) throws Exception { | ||
JavaCompiler compiler = javax.tools.ToolProvider.getSystemJavaCompiler(); | JavaCompiler compiler = javax.tools.ToolProvider.getSystemJavaCompiler(); | ||
- | List<String> arguments = Arrays.asList(args); | + | List<String> arguments = new ArrayList<>(Arrays.asList(args)); |
+ | arguments.add("-d"); | ||
+ | arguments.add("."); | ||
List<JavaFileObject> sources = Collections.singletonList(new Src(CODE)); | List<JavaFileObject> sources = Collections.singletonList(new Src(CODE)); | ||
JavaCompiler.CompilationTask task = compiler.getTask(null, null, null, arguments, null, sources); | JavaCompiler.CompilationTask task = compiler.getTask(null, null, null, arguments, null, sources); | ||
Line 87: | Line 90: | ||
Can we fix that? Sure... | Can we fix that? Sure... | ||
- | The idea would be to replace the standard "compiler tool" with the one coming from the [[frgaal]] project. 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 | + | The idea would be to replace the standard "compiler tool" with the one coming from the [[frgaal]] project. 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 disable standard [[JavaC]]: |
<source lang="bash"> | <source lang="bash"> | ||
Line 97: | Line 100: | ||
<source lang="bash"> | <source lang="bash"> | ||
- | + | $ curl -o compiler.jar https://repo1.maven.org/maven2/org/frgaal/compiler/20.0.0/compiler-20.0.0.jar | |
- | + | ||
- | $ curl -o compiler.jar https://repo1.maven.org/maven2/org/frgaal/compiler/ | + | |
$ /jdk-11/bin/java --limit-modules java.base,jdk.zipfs -cp compiler.jar:. ModernJavaCompiler | $ /jdk-11/bin/java --limit-modules java.base,jdk.zipfs -cp compiler.jar:. ModernJavaCompiler | ||
- | |||
- | |||
- | |||
Compiled OK | Compiled OK | ||
- | + | $ /jdk-11/bin/java R | |
R[name=Hello World!] | R[name=Hello World!] | ||
</source> | </source> | ||
Line 111: | Line 109: | ||
Hey, using '''record''' on JDK-11! | Hey, using '''record''' on JDK-11! | ||
- | Having '''record''' (and other [[JDK]]- | + | Having '''record''' (and other [[JDK]]-20 language features) available on old JDKs is great, isn't it? |
Embed [[Frgaal]] into your own programs and use the latest [[Java]] features on any [[JDK]]! | Embed [[Frgaal]] into your own programs and use the latest [[Java]] features on any [[JDK]]! |
Current revision
I love Frgaal and you'll love it too: Wouldn't it be great to have records and other latest Java language features available on your old JDKs? 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?
Let's imagine we have a following code invoking the JavaCompiler via ToolProvider for a custom CODE snippet defining Record with main method:
import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; 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) {\n" + " public static void main(String... args) {\n" + " System.out.println(new R(\"Hello World!\"));\n" + " }\n" + "}\n"; public static void main(String... args) throws Exception { JavaCompiler compiler = javax.tools.ToolProvider.getSystemJavaCompiler(); List<String> arguments = new ArrayList<>(Arrays.asList(args)); arguments.add("-d"); arguments.add("."); List<JavaFileObject> sources = Collections.singletonList(new Src(CODE)); JavaCompiler.CompilationTask task = compiler.getTask(null, null, null, arguments, null, sources); 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 regular Java source file that can be compiled using standard Javac compiler:
$ javac -source 8 -target 8 ModernJavaCompiler.java
The ModernJavaCompiler source code then uses JavaCompiler on its own to generate class R. It can be executed JDK-17 as
$ /jdk-17/bin/java ModernJavaCompiler Compiled OK $ /jdk-17/bin/java R R[name=Hello World!]
However executing the same steps with JDK-11 is going to fail as the Javac from JDK-11 doesn't support record keyword:
$ /jdk11/bin/java ModernJavaCompiler Code.java:1: error: class, interface, or enum expected record R (String name) { ^
Can we fix that? Sure...
The idea would be to replace the standard "compiler tool" with the one coming from the frgaal project. 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 disable standard JavaC:
$ /jdk11/bin/java --limit-modules java.base ModernJavaCompiler Exception in thread "main" java.lang.NoClassDefFoundError: javax/tools/ToolProvider
Great! 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:
$ curl -o compiler.jar https://repo1.maven.org/maven2/org/frgaal/compiler/20.0.0/compiler-20.0.0.jar $ /jdk-11/bin/java --limit-modules java.base,jdk.zipfs -cp compiler.jar:. ModernJavaCompiler Compiled OK $ /jdk-11/bin/java R R[name=Hello World!]
Hey, using record on JDK-11!
Having record (and other JDK-20 language features) available on old JDKs is great, isn't it?
Embed Frgaal into your own programs and use the latest Java features on any JDK!