cincheo / jsweet

A Java to JavaScript transpiler.
http://www.jsweet.org
Other
1.45k stars 159 forks source link

Java 17 LTS minimal support #710

Open workmanw opened 2 years ago

workmanw commented 2 years ago

Hello,

We are in the process of upgrading to Java 17 LTS and noticed this issue when trying to compile our library with jsweet. This appears to be an issue with the jsweet transpiler itself, but if I'm mistaken please let me know and I'll file the issue where ever.

Version:

[ERROR] failed to create transpiler
java.lang.RuntimeException: fail to initialize extension classpath
    at org.jsweet.transpiler.extension.ExtensionManager.initExtensionClassPath (ExtensionManager.java:157)
    at org.jsweet.transpiler.extension.ExtensionManager.checkAndCompileExtension (ExtensionManager.java:73)
    at org.jsweet.transpiler.JSweetTranspiler.<init> (JSweetTranspiler.java:535)
    at org.jsweet.AbstractJSweetMojo.createJSweetTranspiler (AbstractJSweetMojo.java:309)
    at org.jsweet.JSweetMojo.execute (JSweetMojo.java:41)
    at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo (DefaultBuildPluginManager.java:137)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:210)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:156)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:148)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:117)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:81)
    at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build (SingleThreadedBuilder.java:56)
    at org.apache.maven.lifecycle.internal.LifecycleStarter.execute (LifecycleStarter.java:128)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:305)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:192)
    at org.apache.maven.DefaultMaven.execute (DefaultMaven.java:105)
    at org.apache.maven.cli.MavenCli.execute (MavenCli.java:972)
    at org.apache.maven.cli.MavenCli.doMain (MavenCli.java:293)
    at org.apache.maven.cli.MavenCli.main (MavenCli.java:196)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:77)
    at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke (Method.java:568)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced (Launcher.java:282)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launch (Launcher.java:225)
    at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode (Launcher.java:406)
    at org.codehaus.plexus.classworlds.launcher.Launcher.main (Launcher.java:347)
Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make protected void java.net.URLClassLoader.addURL(java.net.URL) accessible: module java.base does not "opens java.net" to unnamed module @1467f2e9
    at java.lang.reflect.AccessibleObject.checkCanSetAccessible (AccessibleObject.java:354)
    at java.lang.reflect.AccessibleObject.checkCanSetAccessible (AccessibleObject.java:297)
    at java.lang.reflect.Method.checkCanSetAccessible (Method.java:199)
    at java.lang.reflect.Method.setAccessible (Method.java:193)
    at org.jsweet.transpiler.extension.ExtensionManager.initExtensionClassPath (ExtensionManager.java:144)
    at org.jsweet.transpiler.extension.ExtensionManager.checkAndCompileExtension (ExtensionManager.java:73)
    at org.jsweet.transpiler.JSweetTranspiler.<init> (JSweetTranspiler.java:535)
    at org.jsweet.AbstractJSweetMojo.createJSweetTranspiler (AbstractJSweetMojo.java:309)
    at org.jsweet.JSweetMojo.execute (JSweetMojo.java:41)
    at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo (DefaultBuildPluginManager.java:137)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:210)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:156)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:148)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:117)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:81)
    at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build (SingleThreadedBuilder.java:56)
    at org.apache.maven.lifecycle.internal.LifecycleStarter.execute (LifecycleStarter.java:128)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:305)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:192)
    at org.apache.maven.DefaultMaven.execute (DefaultMaven.java:105)
    at org.apache.maven.cli.MavenCli.execute (MavenCli.java:972)
    at org.apache.maven.cli.MavenCli.doMain (MavenCli.java:293)
    at org.apache.maven.cli.MavenCli.main (MavenCli.java:196)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:77)
    at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke (Method.java:568)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced (Launcher.java:282)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launch (Launcher.java:225)
    at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode (Launcher.java:406)
    at org.codehaus.plexus.classworlds.launcher.Launcher.main (Launcher.java:347)
lgrignon commented 2 years ago

Hello. Thanks for reporting. Did you try with another JDK (oracle’s one for instance)?

workmanw commented 2 years ago

@lgrignon Hello. Thanks for the quick response and suggestion. This morning I tried with both Oracle's JDK 17 and Adoptium's Temurin. Both JDKs have this issue as well.

Oracle JDK 17:

$ java -version

java version "17.0.1" 2021-10-19 LTS
Java(TM) SE Runtime Environment (build 17.0.1+12-LTS-39)
Java HotSpot(TM) 64-Bit Server VM (build 17.0.1+12-LTS-39, mixed mode, sharing)

Oracle OpenJDK 17:

$ java -version

openjdk version "17" 2021-09-14
OpenJDK Runtime Environment Homebrew (build 17+0)
OpenJDK 64-Bit Server VM Homebrew (build 17+0, mixed mode, sharing)

Adoptium/Temurin

$ java -version

openjdk version "17" 2021-09-14
OpenJDK Runtime Environment Temurin-17+35 (build 17+35)
OpenJDK 64-Bit Server VM Temurin-17+35 (build 17+35, mixed mode, sharing)
lgrignon commented 2 years ago

It definitely sounds like a problem of access to an API in the latest JDK. In the trace we can see that access to addUrl is refused while trying to make it accessible. We need another way to add URL to class loader if this is not possible anymore.

Anyway I am not sure we will find time to dig into this in the near future. Will you? It does not seem too complicated. I would be glad to review PR, if you file one :) I am not sure that you won't encounter more errors after this with J17 though since we didn't try it yet :)

workmanw commented 2 years ago

Hey @lgrignon . Yea I can make sometime over the next few weeks. Do you have the background on what's actually happening with this initialization? Why is jsweet patching this method to use it?

Also, I know it's kind of a nit, but this feels more like a bug than an enhancement.

lgrignon commented 2 years ago

That's amazing :)

Please see here: https://github.com/cincheo/jsweet/blob/develop/transpiler/src/main/java/org/jsweet/transpiler/extension/ExtensionManager.java#L133

This URLClassLoader hack is used to add extension directory to the current class path, and allow extension classes to be compiled on the fly here: https://github.com/cincheo/jsweet/blob/develop/transpiler/src/main/java/org/jsweet/transpiler/extension/ExtensionManager.java#L121

(At least it is my understanding of it :))

I guess there is a more modern approach of doing this because it's a very old technique.

Note : I tagged this issue as enhancement because Java 17 support is an enhancement ;) I will change this issue's subject to reflect it

lgrignon commented 2 years ago

Note : for a full Java 17 support, we would need to implement new language constructs (from https://docs.oracle.com/en/java/javase/17/docs/api/jdk.compiler/com/sun/source/tree/TreeVisitor.html)

I will change again the subject because I think this is beyond the scope of this issue

nedtwigg commented 2 years ago

I was able to run JSweet on Java 17 by adding the following to gradle.properties:

org.gradle.jvmargs=-Dfile.encoding=UTF-8 \
  --add-opens jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED \
  --add-opens jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED \
  --add-opens jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED \
  --add-opens jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED \
  --add-opens jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED \
  --add-opens jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED \
  --add-opens jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED
lgrignon commented 2 years ago

Hey @nedtwigg that’s amazing! Well done. Do you want to file a PR ? I would merge it right away

nedtwigg commented 2 years ago

My workaround has to be added to the gradle.properties of the project that is using JSweet, I don't know of a way to implement this fix as a PR.

vorth commented 1 year ago

You are my hero, @nedtwigg! This unblocked me, and I'm back to normal transpiler error fixing. Thank you!