spring-attic / spring-native

Spring Native is now superseded by Spring Boot 3 official native support

Home Page:https://docs.spring.io/spring-boot/docs/current/reference/html/native-image.html

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Signer information SecurityException when building executable with native-image command

moarychan opened this issue · comments

Describe the issue
There's module com.azure.spring:spring-cloud-azure-native-configuration to enable the Spring Native support for Spring Cloud Azure libraries, when building executable with Spring native support, the following exceptions have occurred:
Fatal error: java.lang.SecurityException: class "com.azure.spring.cloud.autoconfigure.compatibility.AzureCompatibilityVerifierAutoConfiguration"'s signer information does not match signer information of other classes in the same package

Or this class exception,
Error: Error loading a referenced type: java.lang.SecurityException: class "com.azure.spring.cloud.autoconfigure.compatibility.ContextBootstrapInitializer"'s signer information does not match signer information of other classes in the same package

If I run the command mvn clean package, then the below similar exception occurs:
Caused by: java.lang.SecurityException: class "com.azure.spring.cloud.autoconfigure.compatibility.IssueAzureStorageNativeApplicationTestsContextInitializer"'s signer information does not match signer information of other classes in the same package.

If I run mvn clean spring-boot:run, it can run successfully.

Before I push the artifacts to Maven, I can run native-image command locally success with local Spring Cloud Azure artifacts, the difference between the artifacts is that the artifacts of Maven have the extra digest information than the local artifacts. Please help to address this exception, thanks!

Steps to reproduce the issue
You can follow the sample project readme doc to reproduce this issue, it will connect to the local Azure Storage emulator.

Describe GraalVM and your environment:

  • GraalVM version (latest snapshot builds can be found here), or commit id if built from source: CE 22.0.0.2
  • JDK major version: 11
  • OS: Windows 11
  • Architecture: AMD64
  • x64 Native Tools Command Prompt: VS 2019
  • Spring Boot: 2.6.6
  • Spring Native: 0.11.4

More details
Here is the details log.

Fatal error: java.lang.SecurityException: class "com.azure.spring.cloud.autoconfigure.compatibility.AzureCompatibilityVerifierAutoConfiguration"'s signer information does not match signer information of other classes in the same package
        at java.base/java.lang.ClassLoader.checkCerts(ClassLoader.java:1151)
        at java.base/java.lang.ClassLoader.preDefineClass(ClassLoader.java:906)
        at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1015)
        at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:174)
        at java.base/java.net.URLClassLoader.defineClass(URLClassLoader.java:555)
        at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:458)
        at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:452)
        at java.base/java.security.AccessController.doPrivileged(Native Method)
        at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:451)
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:589)
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
        at java.base/java.lang.Class.forName0(Native Method)
        at java.base/java.lang.Class.forName(Class.java:398)
        at com.oracle.svm.hosted.ImageClassLoader.forName(ImageClassLoader.java:285)
        at com.oracle.svm.hosted.ImageClassLoader.findClass(ImageClassLoader.java:278)
        at com.oracle.svm.hosted.config.ReflectionRegistryAdapter.resolveType(ReflectionRegistryAdapter.java:68)
        at com.oracle.svm.core.configure.ReflectionConfigurationParser.parseClass(ReflectionConfigurationParser.java:94)
        at com.oracle.svm.core.configure.ReflectionConfigurationParser.parseClassArray(ReflectionConfigurationParser.java:77)
        at com.oracle.svm.core.configure.ReflectionConfigurationParser.parseAndRegister(ReflectionConfigurationParser.java:72)
        at com.oracle.svm.hosted.config.ConfigurationParserUtils.doParseAndRegister(ConfigurationParserUtils.java:127)
        at com.oracle.svm.hosted.config.ConfigurationParserUtils.lambda$parseAndRegisterConfigurations$3(ConfigurationParserUtils.java:113)
        at java.base/java.util.stream.ReferencePipeline$4$1.accept(ReferencePipeline.java:212)
        at com.oracle.svm.hosted.config.ConfigurationParserUtils$1.tryAdvance(ConfigurationParserUtils.java:106)
        at java.base/java.util.Spliterator.forEachRemaining(Spliterator.java:326)
        at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:658)
        at java.base/java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:274)
        at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1655)
        at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
        at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
        at java.base/java.util.stream.StreamSpliterators$WrappingSpliterator.forEachRemaining(StreamSpliterators.java:312)
        at java.base/java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:734)
        at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
        at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
        at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913)
        at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
        at java.base/java.util.stream.IntPipeline.reduce(IntPipeline.java:491)
        at java.base/java.util.stream.IntPipeline.sum(IntPipeline.java:449)
        at com.oracle.svm.hosted.config.ConfigurationParserUtils.parseAndRegisterConfigurations(ConfigurationParserUtils.java:115)
        at com.oracle.svm.reflect.hosted.ReflectionFeature.duringSetup(ReflectionFeature.java:185)
        at com.oracle.svm.hosted.NativeImageGenerator.lambda$setupNativeImage$16(NativeImageGenerator.java:847)
        at com.oracle.svm.hosted.FeatureHandler.forEachFeature(FeatureHandler.java:74)
        at com.oracle.svm.hosted.NativeImageGenerator.setupNativeImage(NativeImageGenerator.java:847)
        at com.oracle.svm.hosted.NativeImageGenerator.doRun(NativeImageGenerator.java:534)
        at com.oracle.svm.hosted.NativeImageGenerator.run(NativeImageGenerator.java:494)
        at com.oracle.svm.hosted.NativeImageGeneratorRunner.buildImage(NativeImageGeneratorRunner.java:426)
        at com.oracle.svm.hosted.NativeImageGeneratorRunner.build(NativeImageGeneratorRunner.java:587)
        at com.oracle.svm.hosted.NativeImageGeneratorRunner.main(NativeImageGeneratorRunner.java:126)
        at com.oracle.svm.hosted.NativeImageGeneratorRunner$JDK9Plus.main(NativeImageGeneratorRunner.java:617)

Hey! Did you try to report that issue to the authors of com.azure.spring:spring-cloud-azure-native-configuration?

Hi @mhalbritter , thanks for your update! I'm involved in this module, but I haven't found the reason and the solution yet! could you help give some suggestions?

This looks like some class loading issue to me, not sure if related to spring native. Can these classes be loaded in a non-spring application running in a native image?

No, I don't know how to do the test, could you help give a reference doc to test the similar library features?

There is no reference documentation for that. I would create a plain java application with maven or gradle, add the com.azure.spring:spring-cloud-azure-native-configuration as a dependency, write a main method and then a

System.out.println(new com.azure.spring.cloud.autoconfigure.compatibility.AzureCompatibilityVerifierAutoConfiguration())

in there. This will cause the class to be loaded. Then compile the thing using the Native Build Tools to a native image. Then run that image and see if it crashes the same way. If it does, then it's not related to Spring Native and you can create an issue on the GraalVM repo.

I have tested the class loading withe command mvn clean spring-boot:run, which will call Class.forName(xxx), and the application runs fine. I will follow your proposal to do more tests.

Not only is the class AzureCompatibilityVerifierAutoConfiguration, but sometimes also occurs in other classes, the class com.azure.spring.cloud.autoconfigure.compatibility.ContextBootstrapInitializer is generated by Spring Native, it's not in the dependency, can this class exception help to figure out what's wrong?

Hi @mhalbritter , after I test your proposal scenario, it builds successfully without any exceptions.
image

Use Native Build Tools to a native image failed due to the log4j initialization, it has been executed to [2/7] Performing analysis, it is after the above security exception execution phase.
image

I tried to fix the exceptions, but I need to research to find more configurations to solve, the test code is hosted in a new branch non-spring-app-build-demo. @mhalbritter Does this test show that it is related to Spring Native side?

Your error above is related to build time initialization.

I fiddled with your sample and the class loading works when putting the code in the main method. My guess is that the code which Spring Native generates and resides in the same package clashes with the digital signatures which are in the spring-cloud-azure-autoconfigure JAR.

I can reproduce even on the JVM by creating a class com.azure.spring.cloud.autoconfigure.compatibility.Foobar and try to new that in the main method:

Exception in thread "main" java.lang.SecurityException: class "com.azure.spring.cloud.autoconfigure.compatibility.Foobar"'s signer information does not match signer information of other classes in the same package
	at java.base/java.lang.ClassLoader.checkCerts(ClassLoader.java:1158)
	at java.base/java.lang.ClassLoader.preDefineClass(ClassLoader.java:902)
	at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1010)
	at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:150)
	at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:862)
	at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:760)
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:681)
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:639)
	at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)
	at com.example.issue.azurestoragenative.BuildDemo.main(BuildDemo.java:9)

@sdeleuze Have you seen something like this in the past? This could lead to a problem in SB3/SF6, as AFAIK we generate code in the same package as the spring beans.

Hi @mhalbritter could you please help to find a workable solution?

The only workaround I see here is to remove the digital signatures from the spring-cloud-azure-autoconfigure JAR.

Not seen something like this yet, but worth creating a SB3/SF6 repro and report on Spring Framework bug tracker if confirmed.

Let's tackle that issue on Spring Framework 6 side.