英文:
When building a native quarkus image, how should I (re-)structure my code to enable runtime class initialization?
问题
我正在使用Quarkus构建本地镜像,但Graal分析失败并显示以下错误:
错误: 不允许在镜像堆中存在sun.security.provider.NativePRNG的实例,因为此类应在镜像运行时初始化。该对象已经在没有本地镜像初始化工具的情况下进行了初始化,无法跟踪堆栈跟踪。
详细消息:
跟踪:对象通过以下方式访问
读取常量java.security.SecureRandom@472a6481的字段java.security.SecureRandom.secureRandomSpi
扫描方法com.nimbusds.oauth2.sdk.id.Identifier.<init>(Identifier.java:112)达到
从入口点到com.nimbusds.oauth2.sdk.id.Identifier.<init>(int)的调用路径:
在com.nimbusds.oauth2.sdk.id.Identifier.<init>(Identifier.java:105)
在com.nimbusds.oauth2.sdk.token.Token.<init>(Token.java:62)
在com.nimbusds.oauth2.sdk.token.AccessToken.<init>(AccessToken.java:121)
在com.nimbusds.oauth2.sdk.token.BearerAccessToken.<init>(BearerAccessToken.java:114)
在ff.service.identity.application.OAuthAccessTokenProvider.generateAccessToken(OAuthAccessTokenProvider.java:78)
在ff.service.identity.application.OAuthAccessTokenProvider.completeAccessTokenGeneration(OAuthAccessTokenProvider.java:62)
在ff.service.identity.application.OAuthAccessTokenProvider_ClientProxy.completeAccessTokenGeneration(OAuthAccessTokenProvider_ClientProxy.zig:198)
在ff.service.identity.application.OAuthService.validateSignedChallenge(OAuthService.java:187)
在ff.service.identity.application.OAuthService_Subclass.validateSignedChallenge$$superaccessor1(OAuthService_Subclass.zig:258)
在ff.service.identity.application.OAuthService_Subclass$$function$$1.apply(OAuthService_Subclass$$function$$1.zig:41)
在sun.security.ec.XECParameters$1.get(XECParameters.java:183)
在com.oracle.svm.core.jdk.SystemPropertiesSupport.initializeLazyValue(SystemPropertiesSupport.java:190)
在com.oracle.svm.core.jdk.SystemPropertiesSupport.getProperty(SystemPropertiesSupport.java:143)
在com.oracle.svm.core.jdk.Target_java_lang_System.getProperty(JavaLangSubstitutions.java:345)
在com.oracle.svm.jni.JNIJavaCallWrappers.jniInvoke_ARRAY:Ljava_lang_System_2_0002egetProperty_00028Ljava_lang_String_2_00029Ljava_lang_String_2(generated:0)
它正确地明确表示应在运行时初始化随机数生成器提供程序的类。但是,与文档中不同,没有给出调用路径,因为:
> 该对象已经在没有本地镜像初始化工具的情况下进行了初始化,无法跟踪堆栈跟踪
我不知道如何重新组织我的代码以支持此操作,而且据我所知,我并没有做什么非常奇怪的事情。为了准备这个问题,我将涉及com.nimbusds类的代码粗暴地移动到了OAuthService和OAuthAccessTokenProvider中。OAuthService仅由我的OAuthResouce使用,即使将这两个服务都标记为@RequestScoped以强制延迟初始化,错误消息仍然没有变化。
当我添加--initialize-at-run-time=ff.service.identity.application.OAuthService时,实际上会收到有关观察到的问题的更少信息。
错误: 在构建镜像期间初始化应在运行时初始化的类:
ff.service.identity.application.OAuthService该类被要求在运行时初始化(来自命令行)。ff.service.identity.application.OAuthService已经在没有本地镜像初始化工具的情况下进行了初始化,无法跟踪堆栈跟踪。请尝试避免初始化导致ff.service.identity.application.OAuthService初始化的类。
com.oracle.svm.core.util.UserError$UserException: 在构建镜像期间初始化应在运行时初始化的类:
ff.service.identity.application.OAuthService该类被要求在运行时初始化(来自命令行)。ff.service.identity.application.OAuthService已经在没有本地镜像初始化工具的情况下进行了初始化,无法跟踪堆栈跟踪。请尝试避免初始化导致ff.service.identity.application.OAuthService初始化的类。
在com.oracle.svm.core.util.UserError.abort(UserError.java:68)
在com.oracle.svm.hosted.classinitialization.ConfigurableClassInitialization.checkDelayedInitialization(ConfigurableClassInitialization.java:518)
在com.oracle.svm.hosted.classinitialization.ClassInitializationFeature.duringAnalysis(ClassInitializationFeature.java:187)
在com.oracle.svm.hosted.NativeImageGenerator.lambda$runPointsToAnalysis$8(NativeImageGenerator.java:720)
在com.oracle.svm.hosted.FeatureHandler.forEachFeature(FeatureHandler.java:70)
在com.oracle.svm.hosted.NativeImageGenerator.runPointsToAnalysis(NativeImageGenerator.java:720)
在com.oracle.svm.hosted.NativeImageGenerator.doRun(NativeImageGenerator.java:538)
在com.oracle.svm.hosted.NativeImageGenerator.lambda$run$0(NativeImageGenerator.java:451)
在java.base/java.util.concurrent.ForkJoinTask$AdaptedRunnableAction.exec(ForkJoinTask.java:1407)
在java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:290)
在java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1020)
在java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1656)
在java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1594)
在java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:177)
我应该避免初始化这些类,但我不知道我做错了什么或其他可能性。我忽略了什么吗?
编辑: 我正在使用Quarkus 1.6.1.Final,使用GraalVM版本20.1.0(Java版本11.0.7)。与--rerun-class-initialization-at-runtime标志相关的解决方案实际上已经被弃用,自GraalVM 19.0.0以来(我找不到链接):
> 警告:使用已弃用的选
英文:
I'm building a native image with quarkus and the graal analysis fails with the error:
Error: No instances of sun.security.provider.NativePRNG are allowed in the image heap as this class should be initialized at image runtime. Object has been initialized without the native-image initialization instrumentation and the stack trace can't be tracked.
Detailed message:
Trace: Object was reached by
reading field java.security.SecureRandom.secureRandomSpi of
constant java.security.SecureRandom@472a6481 reached by
scanning method com.nimbusds.oauth2.sdk.id.Identifier.<init>(Identifier.java:112)
Call path from entry point to com.nimbusds.oauth2.sdk.id.Identifier.<init>(int):
at com.nimbusds.oauth2.sdk.id.Identifier.<init>(Identifier.java:105)
at com.nimbusds.oauth2.sdk.token.Token.<init>(Token.java:62)
at com.nimbusds.oauth2.sdk.token.AccessToken.<init>(AccessToken.java:121)
at com.nimbusds.oauth2.sdk.token.BearerAccessToken.<init>(BearerAccessToken.java:114)
at ff.service.identity.application.OAuthAccessTokenProvider.generateAccessToken(OAuthAccessTokenProvider.java:78)
at ff.service.identity.application.OAuthAccessTokenProvider.completeAccessTokenGeneration(OAuthAccessTokenProvider.java:62)
at ff.service.identity.application.OAuthAccessTokenProvider_ClientProxy.completeAccessTokenGeneration(OAuthAccessTokenProvider_ClientProxy.zig:198)
at ff.service.identity.application.OAuthService.validateSignedChallenge(OAuthService.java:187)
at ff.service.identity.application.OAuthService_Subclass.validateSignedChallenge$$superaccessor1(OAuthService_Subclass.zig:258)
at ff.service.identity.application.OAuthService_Subclass$$function$$1.apply(OAuthService_Subclass$$function$$1.zig:41)
at sun.security.ec.XECParameters$1.get(XECParameters.java:183)
at com.oracle.svm.core.jdk.SystemPropertiesSupport.initializeLazyValue(SystemPropertiesSupport.java:190)
at com.oracle.svm.core.jdk.SystemPropertiesSupport.getProperty(SystemPropertiesSupport.java:143)
at com.oracle.svm.core.jdk.Target_java_lang_System.getProperty(JavaLangSubstitutions.java:345)
at com.oracle.svm.jni.JNIJavaCallWrappers.jniInvoke_ARRAY:Ljava_lang_System_2_0002egetProperty_00028Ljava_lang_String_2_00029Ljava_lang_String_2(generated:0)
It correctly and logically states that the class for the random number generator provider should be initialised at runtime. However, unlike in the docs, no call path is given because the:
> Object has been initialized without the native-image initialization instrumentation and the stack trace can't be tracked
I don't know how to go about restructuring my code to support this, and I'm not doing anything really exotic, as far as I can tell. To prepare this question, I brutally moved the code together involving classes from com.nimbusds, and it now resides in OAuthService and OAuthAccessTokenProvider. OAuthService is only used by my OAuthResouce, and even after making these two services @RequestScoped to enforce lazy initialization, the error message remains unchanged.
When I add --initialize-at-run-time=ff.service.identity.application.OAuthService, I actually receive less information about the observed problem.
Error: Classes that should be initialized at run time got initialized during image building:
ff.service.identity.application.OAuthService the class was requested to be initialized at run time (from the command line). ff.service.identity.application.OAuthService has been initialized without the native-image initialization instrumentation and the stack trace can't be tracked. Try avoiding to initialize the class that caused initialization of ff.service.identity.application.OAuthService
com.oracle.svm.core.util.UserError$UserException: Classes that should be initialized at run time got initialized during image building:
ff.service.identity.application.OAuthService the class was requested to be initialized at run time (from the command line). ff.service.identity.application.OAuthService has been initialized without the native-image initialization instrumentation and the stack trace can't be tracked. Try avoiding to initialize the class that caused initialization of ff.service.identity.application.OAuthService
at com.oracle.svm.core.util.UserError.abort(UserError.java:68)
at com.oracle.svm.hosted.classinitialization.ConfigurableClassInitialization.checkDelayedInitialization(ConfigurableClassInitialization.java:518)
at com.oracle.svm.hosted.classinitialization.ClassInitializationFeature.duringAnalysis(ClassInitializationFeature.java:187)
at com.oracle.svm.hosted.NativeImageGenerator.lambda$runPointsToAnalysis$8(NativeImageGenerator.java:720)
at com.oracle.svm.hosted.FeatureHandler.forEachFeature(FeatureHandler.java:70)
at com.oracle.svm.hosted.NativeImageGenerator.runPointsToAnalysis(NativeImageGenerator.java:720)
at com.oracle.svm.hosted.NativeImageGenerator.doRun(NativeImageGenerator.java:538)
at com.oracle.svm.hosted.NativeImageGenerator.lambda$run$0(NativeImageGenerator.java:451)
at java.base/java.util.concurrent.ForkJoinTask$AdaptedRunnableAction.exec(ForkJoinTask.java:1407)
at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:290)
at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1020)
at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1656)
at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1594)
at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:177)
I'm supposted to avoid initializing these classes, but I don't know what I'm doing wrong or what other possibilities exist. What have I overseen?
EDIT: I am building with Quarkus 1.6.1.Final, using GraalVM Version 20.1.0 (Java Version 11.0.7).
A solution involving the flag --rerun-class-initialization-at-runtime is actually deprecated since GraalVM 19.0.0 (I can't find a link):
> Warning: Using a deprecated option --rerun-class-initialization-at-runtime. Currently there is no replacement for this option. Try using --initialize-at-run-time or use the non-API option -H:ClassInitialization directly.
答案1
得分: 1
你可能需要使用 rerun-class-initialization-at-runtime= com.nimbusds.oauth2.sdk.id.Identifier
英文:
Most likely you need to use rerun-class-initialization-at-runtime= com.nimbusds.oauth2.sdk.id.Identifier
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论