eclipse-jdt / eclipse.jdt.core

Eclipse Public License 2.0
161 stars 130 forks source link

Multi-Release JAR is not recognized as such #2495

Open eitan-rosenberg opened 5 months ago

eitan-rosenberg commented 5 months ago

Recently, I update com.google.code.gson:gson to version 2.11.0 from version 2.10.1.

The project use module-info.java and use "requires com.google.gson;"

gson-2.11.0.jar is a Multi-Release JAR and the module declaration is at META-INF/versions/9/module-info.class

I open an issue and it got the full details. Also included in that issue a small project to demonstrate the problem.(https://github.com/google/gson/files/15412480/ModuleTest.zip)

When using pure maven build "mvn clean test" it is compiled successfully. Also I can run it using "mvn compile exec:java -Dexec.mainClass="main.Main"" .

I use: M2E Maven Integration for Eclipse Core 2.6.0.20240220-1109 Eclipse 2024-03 (4.31) Java openjdk version "22.0.1" 2024-04-16

Thanks in advance for any response.

eitan-rosenberg commented 4 months ago

Hi there... Anyone at home ?

eitan-rosenberg commented 4 months ago

Solved for me by recompile with java 22

howlger commented 3 months ago

Steps to reproduce this issue

  1. Create a new Java project name Sample of Java 9 or higher with the option Create module-info.java
  2. Add the com.networknt:json-schema-validator:1.4.3 JAR to the build path
  3. Edit the module-info.java as follows:

    module Sample {
    
        requires json.schema.validator; // module name mistakenly derived from the file name "json-schema-validator-1.4.3.jar"
    
        // ... instead of from "META-INF/versions/9/module-info.class" as follows:
        requires com.networknt.schema;
        //       ~~~~~~~~~~~~~~~~~~~~
        //       com.networknt.schema cannot be resolved to a module
    
    }

Expected: requires json.schema.validator; should give an error and requires com.networknt.schema; should work instead.

Workarounds

As a workaround, do one of the following:

See also

Marcono1234 commented 2 months ago

It seems this is related to the moditect-maven-plugin. For Gson and json-schema-validator it looks like this issue started occurring when they updated moditect-maven-plugin to 1.2.0.Final (for Gson 2.10.1 → 2.11.0; for json-schema-validator 1.4.0 → 1.4.1).

I am not completely sure where exactly the issue is within jdt.core and if there are multiple classes affected (please double check!), but I could at least find one location: https://github.com/eclipse-jdt/eclipse.jdt.core/blob/ed787f542d5509ba226f0b8b06982d61e81b4622/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathMultiReleaseJar.java#L83-L85

Here is an example for testing this:

public static void main(String[] args) throws Exception {
    System.out.println(getModuleName("gson-2.10.1.jar"));
    System.out.println(getModuleName("gson-2.11.0.jar"));

    System.out.println(getModuleName("json-schema-validator-1.4.0.jar"));
    System.out.println(getModuleName("json-schema-validator-1.4.1.jar"));
}

static String getModuleName(String path) throws Exception {
    AccessRuleSet accessRuleSet = new AccessRuleSet(new AccessRule[0], AccessRestriction.LIBRARY, "test");
    ClasspathJar classpathJar = new ClasspathMultiReleaseJar(new ZipFile(path), accessRuleSet, true, "9");
    // Initialize module information
    new ModulePathEntry(new Path(path), classpathJar);
    return new String(classpathJar.getModule().name());
}

(tested with org.eclipse.jdt:org.eclipse.jdt.core:3.38.0)

The code in ClasspathMultiReleaseJar assumes that for multi-release JARs a (directory) entry exists, e.g. META-INF/versions/9/. However, https://github.com/moditect/moditect/pull/230 (accidentally?) changed the JAR modification code to not generate that entry anymore, but only the META-INF/versions/9/module-info.class entry.

It is not completely clear if that directory entry is required. The JAR specification talks about the "directory" but it does not explicitly say that this directory must exist as ZIP entry.

javac does not seem to care whether the ZIP directory entry exists or not.


There seems to be some duplication regarding multi-release handling in jdt.core, at least these classes all have logic for META-INF/versions:

Confusingly though org.eclipse.jdt.core.JavaCore.getModuleNameFromJar(File) and getRequiredModulesFromJar have no handling for multi-release JARs.

And I think so far I also haven't seen any Multi-Release: true check, despite the JAR specification requiring this for JARs to be recognized as multi-release JARs.

Marcono1234 commented 2 months ago

As side note: This only affects JDT within the Eclipse IDE. The ECJ batch compiler does not properly support modular multi-release JARs at all, see https://bugs.eclipse.org/bugs/show_bug.cgi?id=577790 / #2778 and #61.

gv2011 commented 2 weeks ago

Probably related: Bugzilla – Bug 534624 Support module-info.java in multi-release JAR files

I have the same problem AndreasWBartels described.