英文:
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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论