Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error when running on Java 21-ea #310

Closed
beikov opened this issue May 27, 2023 · 11 comments · Fixed by #312
Closed

Error when running on Java 21-ea #310

beikov opened this issue May 27, 2023 · 11 comments · Fixed by #312

Comments

@beikov
Copy link

beikov commented May 27, 2023

Trying to run the 3.1.1 Maven plugin with Java 21-ea, I get the following error:

Error:  Failed to execute goal io.smallrye:jandex-maven-plugin:3.1.1:jandex (make-index) on project blaze-persistence-integration-graphql-spqr: A type incompatibility occurred while executing io.smallrye:jandex-maven-plugin:3.1.1:jandex: class java.lang.Object cannot be cast to class [B (java.lang.Object and [B are in module java.base of loader 'bootstrap')
Error:  -----------------------------------------------------
Error:  realm =    plugin>io.smallrye:jandex-maven-plugin:3.1.1
Error:  strategy = org.codehaus.plexus.classworlds.strategy.SelfFirstStrategy
Error:  urls[0] = file:/home/runner/.m2/repository/io/smallrye/jandex-maven-plugin/3.1.1/jandex-maven-plugin-3.1.1.jar
Error:  urls[1] = file:/home/runner/.m2/repository/org/codehaus/plexus/plexus-utils/3.5.0/plexus-utils-3.5.0.jar
Error:  urls[2] = file:/home/runner/.m2/repository/io/smallrye/jandex/3.1.1/jandex-3.1.1.jar
Error:  Number of foreign imports: 1
Error:  import: Entry[import  from realm ClassRealm[maven.api, parent: null]]

Any idea what the issue could be?

Apache Maven 3.6.3 (cecedd343002696d0abb50b32b541b8a6ba2883f)
Maven home: /home/runner/.m2/wrapper/dists/apache-maven-3.6.3-bin/1iopthnavndlasol9gbrbg6bf2/apache-maven-3.6.3
Java version: 21-ea, vendor: Azul Systems, Inc., runtime: /opt/hostedtoolcache/Java_Zulu_jdk/21.0.0-ea.22/x64
Default locale: en, platform encoding: UTF-8
OS name: "linux", version: "5.15.0-1037-azure", arch: "amd64", family: "unix"

@Ladicek
Copy link
Contributor

Ladicek commented May 29, 2023

I've downloaded https://search.maven.org/artifact/com.blazebit/blaze-persistence-integration-graphql-spqr/1.6.8/jar and trying to index it with these JDKs:

openjdk version "21-beta" 2023-09-19
OpenJDK Runtime Environment Temurin-21+22-202305251619 (build 21-beta+22-202305251619)
OpenJDK 64-Bit Server VM Temurin-21+22-202305251619 (build 21-beta+22-202305251619, mixed mode, sharing)
openjdk version "21-ea" 2023-09-19
OpenJDK Runtime Environment Zulu21+57-CA (build 21-ea+22)
OpenJDK 64-Bit Server VM Zulu21+57-CA (build 21-ea+22, mixed mode, sharing)

They both seem to work just fine (as in, they write an index file and don't fail).

Could you please provide a JAR on which indexing fails? Alternatively, a stack trace might be enough (mvn -X).

@beikov
Copy link
Author

beikov commented May 30, 2023

The problem appears when the module is compiled with the Java 21 class file version. I guess it doesn't really matter what the content of the JAR file is, as long as there is one class file compiled with the latest version.

@beikov
Copy link
Author

beikov commented May 30, 2023

So far, I reproduced this issue locally with Azul Zulu JDK 21-ea build 22. Here is the JAR (added .zip to the end because GitHub doesn't allow uploading JAR files):
blaze-persistence-integration-graphql-spqr-1.6.9-SNAPSHOT.jar.zip

Here is the full error:

Caused by: org.apache.maven.plugin.PluginExecutionException: A type incompatibility occurred while executing io.smallrye:jandex-maven-plugin:3.1.1:jandex: class java.lang.Object cannot be cast to class [B (java.lang.Object and [B are in module java.base of loader 'bootstrap')
-----------------------------------------------------
realm =    plugin>io.smallrye:jandex-maven-plugin:3.1.1
strategy = org.codehaus.plexus.classworlds.strategy.SelfFirstStrategy
urls[0] = file:/C:/Users/cbeikov/.m2/repository/io/smallrye/jandex-maven-plugin/3.1.1/jandex-maven-plugin-3.1.1.jar
urls[1] = file:/C:/Users/cbeikov/.m2/repository/org/codehaus/plexus/plexus-utils/3.5.0/plexus-utils-3.5.0.jar
urls[2] = file:/C:/Users/cbeikov/.m2/repository/io/smallrye/jandex/3.1.1/jandex-3.1.1.jar
Number of foreign imports: 1
import: Entry[import  from realm ClassRealm[maven.api, parent: null]]

-----------------------------------------------------

    at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo (DefaultBuildPluginManager.java:199)
    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:957)
    at org.apache.maven.cli.MavenCli.doMain (MavenCli.java:289)
    at org.apache.maven.cli.MavenCli.main (MavenCli.java:193)
    at jdk.internal.reflect.DirectMethodHandleAccessor.invoke (DirectMethodHandleAccessor.java:103)
    at java.lang.reflect.Method.invoke (Method.java:578)
    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)
    at jdk.internal.reflect.DirectMethodHandleAccessor.invoke (DirectMethodHandleAccessor.java:103)
    at java.lang.reflect.Method.invoke (Method.java:578)
    at org.apache.maven.wrapper.BootstrapMainStarter.start (BootstrapMainStarter.java:39)
    at org.apache.maven.wrapper.WrapperExecutor.execute (WrapperExecutor.java:122)
    at org.apache.maven.wrapper.MavenWrapperMain.main (MavenWrapperMain.java:61)
Caused by: java.lang.ClassCastException: class java.lang.Object cannot be cast to class [B (java.lang.Object and [B are in module java.base of loader 'bootstrap')
    at org.jboss.jandex.StrongInternPool$ByteArrayInternPool.hash (StrongInternPool.java:625)
    at org.jboss.jandex.StrongInternPool.intern (StrongInternPool.java:237)
    at org.jboss.jandex.NameTable.intern (NameTable.java:101)
    at org.jboss.jandex.IndexWriterV2.deepIntern (IndexWriterV2.java:1027)
    at org.jboss.jandex.IndexWriterV2.addMethodList (IndexWriterV2.java:1011)
    at org.jboss.jandex.IndexWriterV2.addClass (IndexWriterV2.java:932)
    at org.jboss.jandex.IndexWriterV2.buildTables (IndexWriterV2.java:888)
    at org.jboss.jandex.IndexWriterV2.write (IndexWriterV2.java:199)
    at org.jboss.jandex.IndexWriter.write (IndexWriter.java:102)
    at org.jboss.jandex.IndexWriter.write (IndexWriter.java:66)
    at org.jboss.jandex.maven.JandexGoal.execute (JandexGoal.java:172)
    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:957)
    at org.apache.maven.cli.MavenCli.doMain (MavenCli.java:289)
    at org.apache.maven.cli.MavenCli.main (MavenCli.java:193)
    at jdk.internal.reflect.DirectMethodHandleAccessor.invoke (DirectMethodHandleAccessor.java:103)
    at java.lang.reflect.Method.invoke (Method.java:578)
    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)
    at jdk.internal.reflect.DirectMethodHandleAccessor.invoke (DirectMethodHandleAccessor.java:103)
    at java.lang.reflect.Method.invoke (Method.java:578)
    at org.apache.maven.wrapper.BootstrapMainStarter.start (BootstrapMainStarter.java:39)
    at org.apache.maven.wrapper.WrapperExecutor.execute (WrapperExecutor.java:122)
    at org.apache.maven.wrapper.MavenWrapperMain.main (MavenWrapperMain.java:61)

@Ladicek
Copy link
Contributor

Ladicek commented May 30, 2023

No, that doesn't seem to reproduce. Do you have a Maven project I can clone and build myself? https://github.com/Blazebit/blaze-persistence doesn't seem to use Jandex 3.1.1 anywhere 🤔

@beikov
Copy link
Author

beikov commented May 30, 2023

I do. Checkout the contents of this PR and first build with .\mvnw clean install -P "hibernate-5.6,h2,spring-data-2.7.x,deltaspike-1.9" "-Duser.country=US" "-Duser.language=en" "-Dmaven.javadoc.skip" "-Dmain.java.version=21" "-Dtest.java.version=21" "-Djdk8.home=<PATH_TO_JDK_8>" -DskipTests

It will fail at that module, but then you can build just that single module by appending -pl .\integration\graphql-spqr\

@beikov
Copy link
Author

beikov commented May 30, 2023

And don't forget to make sure that your JAVA_HOME env variable points to a JDK 21

@Ladicek
Copy link
Contributor

Ladicek commented May 30, 2023

OK, reproduced it now. Thanks!

@Ladicek
Copy link
Contributor

Ladicek commented May 31, 2023

OK, the issue is caused by the performance improvements made in Jandex 3.1.0. As part of those improvements, the hash table used for object interning was refactored to be more type-safe (with one subclass of the hash table per interned type), but the null marker object was left unchanged (a single new Object() instance). Replacing that global marker object with a per-subclass marker object solves the problem, but isn't exactly nice. I'll see if I can come up with something better.

@Ladicek
Copy link
Contributor

Ladicek commented Jun 1, 2023

I kept digging, because while my last comment is correct, there must be more to it, and indeed I found a really strange behavior of JDK 21.

Say I have these 2 classes:

public class Foo {
    public Foo(String... strings) {
    }
}
public class Bar {
    public Foo getFoo() {
        return new Foo() {};
    }
}

Then compiling them using javac -g *.java and then decompiling the inner class using javap -v -p Bar\$1.class leads to the following results:

JDK 8, 11, 17:

...

  Bar$1(Bar, java.lang.String...);
    descriptor: (LBar;[Ljava/lang/String;)V
    flags: ACC_VARARGS
    Code:
      stack=2, locals=3, args_size=3
         0: aload_0
         1: aload_1
         2: putfield      #1                  // Field this$0:LBar;
         5: aload_0
         6: aload_2
         7: invokespecial #2                  // Method Foo."<init>":([Ljava/lang/String;)V
        10: return
      LineNumberTable:
        line 3: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      11     0  this   LBar$1;
            0      11     1 this$0   LBar;
            0      11     2 strings   [Ljava/lang/String;

...

JDK 21-ea:

...

  Bar$1(Bar, java.lang.String...);
    descriptor: (LBar;[Ljava/lang/String;)V
    flags: (0x0080) ACC_VARARGS
    Code:
      stack=2, locals=3, args_size=3
         0: aload_0
         1: aload_2
         2: invokespecial #1                  // Method Foo."<init>":([Ljava/lang/String;)V
         5: return
      LineNumberTable:
        line 3: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       6     0  this   LBar$1;
            0       6     1 this$0   LBar;
            0       6     2 strings   [Ljava/lang/String;
    MethodParameters:
      Name                           Flags
      <no name>                      final mandated
      <no name>

...

That is, javac from JDK 21-ea produces the MethodParameters attribute even if -parameters was not used. The attribute has a name_index of 0 for each parameter, which is valid per the JVMS, but Jandex can't cope with it. So that needs fixing too.

@Ladicek
Copy link
Contributor

Ladicek commented Jun 1, 2023

Aside: if -parameters is passed to javac, then the MethodParameters attribute is as-expected on all tested JDKs:

    MethodParameters:
      Name                           Flags
      this$0                         final mandated
      strings

@Ladicek
Copy link
Contributor

Ladicek commented Jun 5, 2023

For historical reference, here are JDK issues that explain the differences in bytecode demonstrated above:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants