Vertispan / j2clmavenplugin

Maven plugin to launch new J2CL compilation
https://vertispan.github.io/j2clmavenplugin/
Apache License 2.0
53 stars 26 forks source link

Cannot provide JRE classes on Java 9+ #153

Open xamde opened 2 years ago

xamde commented 2 years ago

I created a new IT test at https://github.com/Calpano/j2clmavenplugin/tree/main/j2cl-maven-plugin/src/it/lib-with-jre-supersource

I discovered the bug when trying to run the maven plugin from JDK 17 and failed when stumbling over org\dominokit\domino-jackson-super\1.0.0-RC3 so clearly the problem is present in the wild.

Using Java 8 ran the IT test fine. Java 17 broke it.

Here is the detailed description:

Problem Description

When the user tries to supply JRE types on Java 9+, they can currently not be used.

Example

Two projects:

The relevant lines in the build.log are

1) First the compile starts fine ...

[INFO] Starting lib-with-jre-supersource:super:1.0/bytecode
[INFO] lib-with-jre-supersource:super:1.0/bytecode: No JRE emulation for this step on Java >= 9: java.specification.version:17

2) ... then javac determines that java.util.UUID was already in another module, namely in java.base.

[ERROR] lib-with-jre-supersource:super:1.0/bytecode:
   /C:/_data_/_p_/_git/GitHub/j2clmavenplugin/j2cl-maven-plugin/target
   /it-tests/lib-with-jre-supersource/super/src/main/java/java/util/UUID.java:16 
   package exists in another module: java.base

3) After loading the emulated UUID failed, the original UUID causes problems in J2CL.

[ERROR] lib-with-jre-supersource:super:1.0/bytecode:
   /C:/_data_/_p_/_git/GitHub/j2clmavenplugin/j2cl-maven-plugin/target
   /it-tests/lib-with-jre-supersource/super/src/main/java/java/util/UUID.java:43 
   no suitable constructor found for UUID(no arguments)
    constructor java.util.UUID.UUID(byte[]) is not applicable
      (actual and formal argument lists differ in length)
    constructor java.util.UUID.UUID(long,long) is not applicable
      (actual and formal argument lists differ in length)

NOTE: The exact same error can happen not only in bytecode but also in stripped_bytecode.

Solution Ideas

To actually make javac read the new UUID class from our supplied super-library, we must:

And because we don't know which author of JAR dependencies intend on overwriting JRE built-in classes (this set varies between JDK versions), we must put all JARs into the bootClassPath?

But we don't even know, which Java modules is targeted, so need to repeat all JARs to all --patch-module modules?

And we must open all modules? Which java modules besides base exist? java --list-modules tells us:

Conclusion

We should add options in the maven plugin to state entries for --patch-module and --add-reads.

<supersource>
    <module>
        <name>java.base</name>
        <groupId>com.example</groupId>
        <artifactId>libA</artifactId>
        <versions>1.0</version>
    <module>
    <module>
        <name>java.net.http</name>
        <groupId>com.example</groupId>
        <artifactId>libB</artifactId>
        <versions>1.0</version>
    <module>
</supersource>

which results in

--patch-module java.base=.m2/com/example/com-example-libA-1.0.jar java.net.http=.m2/com/example/com-example-libB-1.0.jar
--add-reads java.base=ALL-UNNAMED java.net.http=ALL-UNNAMED