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

Type mismatch in ObjectStreamClass$Caches.localDescs with native image built with latest JDK 17 #4477

Closed
galderz opened this issue Apr 7, 2022 · 13 comments · Fixed by #4485
Assignees
Milestone

Comments

@galderz
Copy link
Contributor

galderz commented Apr 7, 2022

GraalVM master native image fails when built with the very latest JDK 17 code. It throws an error like this:

Error: Type mismatch:
    interface java.util.concurrent.ConcurrentMap static java.util.concurrent.ConcurrentMap com.oracle.svm.core.jdk.Target_java_io_ObjectStreamClass_Caches.localDescs
    class java.io.ClassCache static final java.io.ClassCache java.io.ObjectStreamClass$Caches.localDescs
com.oracle.svm.core.util.UserError$UserException: Type mismatch:
    interface java.util.concurrent.ConcurrentMap static java.util.concurrent.ConcurrentMap com.oracle.svm.core.jdk.Target_java_io_ObjectStreamClass_Caches.localDescs
    class java.io.ClassCache static final java.io.ClassCache java.io.ObjectStreamClass$Caches.localDescs
	at com.oracle.svm.core.util.UserError.abort(UserError.java:72)
	at com.oracle.svm.core.util.UserError.guarantee(UserError.java:96)
	at com.oracle.svm.hosted.substitute.AnnotationSubstitutionProcessor.findOriginalField(AnnotationSubstitutionProcessor.java:829)
	at com.oracle.svm.hosted.substitute.AnnotationSubstitutionProcessor.handleFieldInAliasClass(AnnotationSubstitutionProcessor.java:497)
	at com.oracle.svm.hosted.substitute.AnnotationSubstitutionProcessor.handleAliasClass(AnnotationSubstitutionProcessor.java:401)
	at com.oracle.svm.hosted.substitute.AnnotationSubstitutionProcessor.handleClass(AnnotationSubstitutionProcessor.java:368)
	at com.oracle.svm.hosted.substitute.AnnotationSubstitutionProcessor.init(AnnotationSubstitutionProcessor.java:324)
	at com.oracle.svm.hosted.NativeImageGenerator.createAnnotationSubstitutionProcessor(NativeImageGenerator.java:932)
	at com.oracle.svm.hosted.NativeImageGenerator.setupNativeImage(NativeImageGenerator.java:845)
	at com.oracle.svm.hosted.NativeImageGenerator.doRun(NativeImageGenerator.java:554)
	at com.oracle.svm.hosted.NativeImageGenerator.run(NativeImageGenerator.java:514)
	at com.oracle.svm.hosted.NativeImageGeneratorRunner.buildImage(NativeImageGeneratorRunner.java:407)
	at com.oracle.svm.hosted.NativeImageGeneratorRunner.build(NativeImageGeneratorRunner.java:585)
	at com.oracle.svm.hosted.NativeImageGeneratorRunner.main(NativeImageGeneratorRunner.java:128)
	at com.oracle.svm.hosted.NativeImageGeneratorRunner$JDK9Plus.main(NativeImageGeneratorRunner.java:615)

This is caused by the commit in openjdk/jdk17u-dev@7d132f5.

GraalVM has a subsitution like this:

@TargetClass(value = java.io.ObjectStreamClass.class, innerClass = "Caches")
final class Target_java_io_ObjectStreamClass_Caches {

    @Alias @RecomputeFieldValue(kind = Kind.NewInstance, declClass = ConcurrentHashMap.class) static ConcurrentMap<?, ?> localDescs;

    @Alias @RecomputeFieldValue(kind = Kind.NewInstance, declClass = ConcurrentHashMap.class) static ConcurrentMap<?, ?> reflectors;

    @Alias @RecomputeFieldValue(kind = Kind.NewInstance, declClass = ReferenceQueue.class) private static ReferenceQueue<Class<?>> localDescsQueue;

    @Alias @RecomputeFieldValue(kind = Kind.NewInstance, declClass = ReferenceQueue.class) private static ReferenceQueue<Class<?>> reflectorsQueue;
}

But the JDK 17 API has changed and the type of localDescs is now ClassCache instead of ConcurrentMap.

@galderz
Copy link
Contributor Author

galderz commented Apr 7, 2022

To be more specific, this affects JDK 17.0.4+.

@galderz
Copy link
Contributor Author

galderz commented Apr 11, 2022

I'm trying to fix this, please assign it to me.

@zakkak
Copy link
Collaborator

zakkak commented Apr 13, 2022

FTR the same issue appears with jdk11u-dev (openjdk/jdk11u-dev@118ec61) and will affect 11.0.15+ 11.0.16+

@galderz
Copy link
Contributor Author

galderz commented Apr 13, 2022

Ah yes, good point. The conditionals need to take that into account too.

@jerboaa
Copy link
Collaborator

jerboaa commented Apr 13, 2022

FTR the same issue appears with jdk11u-dev (openjdk/jdk11u-dev@118ec61) and will affect 11.0.15+

One clarification: By 11.0.15+ you mean JDK 11 >= 11.0.16 right? Because https://bugs.openjdk.java.net/browse/JDK-8277072 is in 11.0.16 onwards.

@zakkak
Copy link
Collaborator

zakkak commented Apr 13, 2022

FTR the same issue appears with jdk11u-dev (openjdk/jdk11u-dev@118ec61) and will affect 11.0.15+

One clarification: By 11.0.15+ you mean JDK 11 >= 11.0.16 right? Because https://bugs.openjdk.java.net/browse/JDK-8277072 is in 11.0.16 onwards.

Correct, thanks for catching this :)

@dougxc
Copy link
Member

dougxc commented Apr 13, 2022

I ran into this while looking into making Native Image work on JDK 19. I have attached the untested patch I came up with so far in case it helps:
8277072.patch.txt

@galderz
Copy link
Contributor Author

galderz commented Apr 13, 2022

@dougxc I sent a PR for this, see #4485. It's not yet complete because I need to add JDK11 condition parts, but I should have that done shortly.

@galderz
Copy link
Contributor Author

galderz commented Apr 13, 2022

Here's a summary of a quick chat with Doug:

  • They're trying to move away from JDK version checks, so Doug's idea to check for presence of java.io.ClassCache is more durable.
  • Rather than having a present and absent condition, we can just have a present condition along with a BooleanSuppliers.not function that negates a BooleanSupplier passed in.

I'll adjust my PR to reflect this.

@galderz
Copy link
Contributor Author

galderz commented Apr 13, 2022

The negation function won't work because annotation values need to be constants.

@zakkak
Copy link
Collaborator

zakkak commented Apr 13, 2022

  • They're trying to move away from JDK version checks, so Doug's idea to check for presence of java.io.ClassCache is more durable.

@dougxc this makes sense but I am concerned it might result in silently not substituting something we should be substituting because the supplier just returns false... We've been bitten by that in quarkus, see quarkusio/quarkus#24768 (comment)

I think it's preferable for GraalVM to crash if we expect it to find a specific class or element in the JDK and it fails, instead of having it silently ignore it. A class or element changing or getting removed from JDK is something that requires our immediate attention in order to ensure the substitutions are still functioning as expected.

@dougxc
Copy link
Member

dougxc commented Apr 13, 2022

I understand your concern. That's exactly why we introduced JDK version specific checks in org.graalvm.compiler.hotspot.GraalHotSpotVMConfigAccess. However, in cases where we can safely get away with feature checks only, I'd prefer that. So, in this specific case, is there a risk of something going wrong silently?

@zakkak
Copy link
Collaborator

zakkak commented Apr 13, 2022

So, in this specific case, is there a risk of something going wrong silently?

No, since in this case there are substitutions for both outcomes of the supplier, I find it highly unlikely to go wrong silently.

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

Successfully merging a pull request may close this issue.

4 participants