Open KafkaProServerless opened 5 months ago
Thanks for looking into this @fernando-valdez
Hi @KafkaProServerless, can you please share more details on how you are building the native image? Are you using the config agent? or are you using the native image gradle/maven plugin?
Also, what is the exact version of GraalVM you are using? If this is not the latest version, can you please try the latest version and share of the problem still happens?
Sure, so, I am using the latest springBoot 3.3.0-RC1. I am building using maven, with the command mvn -Pnative spring-boot:build-image. The graal VM version used is 22.0.1, which I think is very very very recent as of this writing.
Please let me know if I need to provide anything else @fernando-valdez
Thanks. Can you please provide a small project (reproducer) that I can use to reproduce this issue locally? Also, what OS are you using?
Sure, and again thank you for looking into this.
So, here is the setup: I am using ubuntu 22.04.4 LTS
Could you please:
1) download graalissue.zip and unzip it
2) cd inside the folder graalissue (which is a very small one file springboot project)
3) just run mvn clean install
and run the jar
4) at this point, make a http request, something like curl http://localhost:8080/graalissue
5) you should see this output: "It should be 41 here => 41"
Could you please let me know if you got to this point without issue? If yes, that would mean the code is working correctly in non native code If not, I believe it is better to debug a bit before proceeding.
Once done, could you just do perform mvn clean
from here:
1) please run mvn -Pnative spring-boot:build-image
this would create the graalvm native image
2) If the image is successfully created, can you run docker tag docker.io/library/graalissue:0.0.1-SNAPSHOT graalissue:latest
3) from there, just run docker run -p 8080:8080 graalissue:latest
4) same curl again: curl http://localhost:8080/graalissue
5) and you should see something in the log like:
java.io.InvalidClassException: java.util.HashMap; local class incompatible: stream classdesc serialVersionUID = 362498820763181265, local class serialVersionUID = -3563561681480877083
at java.base@22.0.1/java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:598)
at java.base@22.0.1/java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:2063)
at java.base@22.0.1/java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1912)
at java.base@22.0.1/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2237)
at java.base@22.0.1/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1747)
at java.base@22.0.1/java.io.ObjectInputStream$FieldValues.<init>(ObjectInputStream.java:2603)
at java.base@22.0.1/java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2454)
at java.base@22.0.1/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2269)
at java.base@22.0.1/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1747)
at java.base@22.0.1/java.io.ObjectInputStream.readObject(ObjectInputStream.java:525)
at java.base@22.0.1/java.io.ObjectInputStream.readObject(ObjectInputStream.java:483)
Could you please try this and let me know if you reproduce as well?
Please let me know if the example is not clear enough @fernando-valdez
Any update please @fernando-valdez
Thanks for your patience, but I don't think this is a direct issue from the native image. The native image has a closed-world assumption: When using Spring Boot to create native images, a closed-world is assumed, which restricts the dynamic aspects of the application. So serialization can be a sensitive issue here.
The error you see is caused because you are using Java serialization and have two different versions of the same class.
Here is an extract from the java docs:
If a serializable class does not explicitly declare a serialVersionUID, then the serialization runtime will calculate a default serialVersionUID value for that class based on various aspects of the class, as described in the Java Object Serialization Specification. This specification defines the serialVersionUID of an enum type to be 0L. However, it is strongly recommended that all serializable classes other than enum types explicitly declare serialVersionUID values, since the default serialVersionUID computation is highly sensitive to class details that may vary depending on compiler implementations, and can thus result in unexpected InvalidClassExceptions during deserialization.
So you can try to refactor your code to explicitly set the value of the serialVersionUID
attribute.
I hope this helps!
Thank you for the answer. May I ask if you managed to reproduce the issue on your side? @fernando-valdez
And are you suggesting I should refactor java.util.Map ?
@fernando-valdez we should first reproduce this issue, then we should run this with -H:ThrowMissingRegistrationErrors=
and see if the serialization config is missing for some of the classes. Could you please work with @KafkaProServerless to get the reproducer?
Hello @fernando-valdez ,
Please let me know what you need from my side, I will be glad to assist. The issue is still reproducible as of right now
Hello @KafkaProServerless, let me share my updates:
It should be 41 here => 41
It should be 41 here => 0
Used the -H:ThrowMissingRegistrationErrors=
flag to get more information on the classes that require atention, and I got this error:
Exception in thread "main" org.graalvm.nativeimage.MissingReflectionRegistrationError: The program tried to reflectively access class
ch.qos.logback.classic.BasicConfigurato
Exception in thread "main" java.lang.IllegalArgumentException: Unable to instantiate factory class [org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer] for factory type [org.springframework.context.ApplicationContextInitializer]
at org.springframework.core.io.support.SpringFactoriesLoader$FailureHandler.lambda$throwing$0(SpringFactoriesLoader.java:647)
at org.springframework.core.io.support.SpringFactoriesLoader$FailureHandler.lambda$handleMessage$3(SpringFactoriesLoader.java:671)
at org.springframework.core.io.support.SpringFactoriesLoader.instantiateFactory(SpringFactoriesLoader.java:231)
at org.springframework.core.io.support.SpringFactoriesLoader.load(SpringFactoriesLoader.java:206)
at org.springframework.core.io.support.SpringFactoriesLoader.load(SpringFactoriesLoader.java:160)
at org.springframework.boot.SpringApplication.getSpringFactoriesInstances(SpringApplication.java:483)
at org.springframework.boot.SpringApplication.getSpringFactoriesInstances(SpringApplication.java:479)
at org.springframework.boot.SpringApplication.<init>(SpringApplication.java:294)
at org.springframework.boot.SpringApplication.<init>(SpringApplication.java:273)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1354)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1343)
at com.example.graalissue.GraalissueApplication.main(GraalissueApplication.java:21)
at java.base@22.0.1/java.lang.invoke.LambdaForm$DMH/sa346b79c.invokeStaticInit(LambdaForm$DMH)
Caused by: org.graalvm.nativeimage.MissingReflectionRegistrationError: The program tried to reflectively access
Then I tried to use the agent to get all the config file. I used this: java -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image -jar target/graalissue-0.0.1-SNAPSHOT.jar
And I got this:
Logging system failed to initialize using configuration from 'null'
com.oracle.svm.core.jdk.resources.MissingResourceRegistrationError: The program tried to access the resource at path
META-INF/spring/logback-pattern-rules
Created internal ticket: GR-54965
@fernando-valdez can you try adding META-INF/spring/logback-pattern-rules
file to resources-config.json
as the message suggests?
Hello team,
I would like to reach out regarding a small issue.
I have a very simple piece of code in my springboot 3.3 application.
The piece of code is:
This code would run fine on non native image, battle tested in production.
Now, we successfully built a native image.
However, at run time, we would get an issue saying we need to add this
java.util.Collections$UnmodifiableMap
in this fileserialization-config.json
, for line:return (Map<?, ?>) objectInputStream.readObject();
We followed the instructions, not knowing if the instructions were correct to begin with.
After following the instructions, we get this error message:
Therefore, I would like to reach out, asking for help on this issue which is happening only with native images.
How to make
return (Map<?, ?>) objectInputStream.readObject();
work with native image?Thank you for your time and good day!