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

Unable to use AmazonCorrettoCryptoProvider with GraalVM native-image #177

Open
lestephane opened this issue Feb 28, 2022 · 7 comments
Open
Labels
help wanted Extra attention is needed

Comments

@lestephane
Copy link

lestephane commented Feb 28, 2022

As recommended in the configuration section, I call as early as possible, in my application main entry point, com.amazon.corretto.crypto.provider.AmazonCorrettoCryptoProvider.install().

But, if I then use --initialize-at-build-time with GraalVM's native-image, it complains that a java.lang.Thread is created as a side-effect of calling install().

Error: Detected a started Thread in the image heap. Threads running in the image generator are no longer running at image 
runtime.  To see how this object got instantiated use --trace-object-instantiation=java.lang.Thread. The object was probably 
created by a class initializer and is reachable from a static field. You can request class initialization at image runtime by using the 
option --initialize-at-run-time=<class-name>. Or you can write your own initialization methods and call them explicitly from your 
main entry point.
Trace: Object was reached by 
        reading field java.util.concurrent.locks.AbstractOwnableSynchronizer.exclusiveOwnerThread of
                constant java.util.concurrent.locks.ReentrantLock$NonfairSync@78f11bbf reached by 
        reading field java.util.concurrent.locks.ReentrantLock.sync of
                constant java.util.concurrent.locks.ReentrantLock@6bf37934 reached by 
        reading field com.amazon.corretto.crypto.provider.Janitor$Stripe.queueLock of
                constant com.amazon.corretto.crypto.provider.Janitor$Stripe@7b88490d reached by 
        indexing into array
                constant com.amazon.corretto.crypto.provider.Janitor$Stripe[]@7c5f1b50 reached by 
        reading field com.amazon.corretto.crypto.provider.Janitor$JanitorState.stripes of
                constant com.amazon.corretto.crypto.provider.Janitor$JanitorState@38cbe7ef reached by 
        scanning method com.amazon.corretto.crypto.provider.Janitor.register(Janitor.java:50)

The cascade of class initializations goes as follows

  • install() is called on AmazonCorrettoCryptoProvider...
  • ... which loads com.amazon.corretto.crypto.provider.Loader at AmazonCorrettoCryptoProvider:47 (v 1.6.1)
     static {
          if (!Loader.IS_AVAILABLE) {
    
  • ... which loads Janitor at Loader:185
            // Finally start up a cleaning thread if necessary
          RESOURCE_JANITOR = new Janitor();
    
  • ... which starts a cleaner thread at Janitor:319

Is there a way to initialize as much as possible of the provider without creating this thread?

Amazon started adding GraalVM configuration files in SDK libraries. Maybe it's time to do the same for AmazonCorrettoCryptoProvider. In any case, any advice is welcome.

@lestephane lestephane changed the title Running AmazonCorrettoCryptoProvider.install() early at startup causes graalvm native-image to complain when --initialize-at-build-time is in use AmazonCorrettoCryptoProvider.install() early at startup causes graalvm native-image to complain when --initialize-at-build-time is in use Feb 28, 2022
@SalusaSecondus
Copy link
Contributor

Thank you for this report. We really need this thread very early on and create it hear specifically to work around other issues we've encountered by it being lazily created later (and thus descending from some arbitrary other thread in the JVM).

I have not experimented with GraalVM nor tested ACCP with it and will pull in some people who know it better to assist me. However, I do see that the error message above recommends using the --initialize-at-run-time= argument. What happens if you use --initialize-at-run-time=com.amazon.corretto.crypto.provider.Loader ?

@SalusaSecondus SalusaSecondus added the help wanted Extra attention is needed label Mar 2, 2022
@lestephane
Copy link
Author

What I tried:

  • --initialize-at-run-time=com.amazon.corretto.crypto.provider solves the problem, but is overly broad.
  • --initialize-at-run-time=com.amazon.corretto.crypto.provider.Loader does not solve the problem. If you need the error for that, I could add it in a separate comment.

I would prefer it if the AWS team provides the GraalVM configuration directly within the artifact, so that only those classes that require special handling are configured as such.

@SalusaSecondus
Copy link
Contributor

We would certainly appreciate that error. ACCP does lots of static initilization logic to load and configure the native system and supporting resources. I wouldn't really expect anything much more targeted than --initialize-at-run-time=com.amazon.corretto.crypto.provider to work. (When you say it works, have you confirmed that the cryptography actually runs correctly using ACCP?)

I agree that we need to further investigate how this library works with GraalVM. At this point we haven't even tested it and so I cannot guarantee that it works. Since we load and use native system libraries I am uncertain how it interacts with precompilation and initialization.

@lestephane
Copy link
Author

I try my darndest to have GraalVM not initializa the provider at build time:

META-INF/native-image/software.amazon.cryptools.AmazonCorrettoCryptoProvider/native-image.properties

Args=-H:-UseServiceLoaderFeature \
  -H:+TraceServiceLoaderFeature \
  -H:ServiceLoaderFeatureExcludeServices=com.amazon.corretto.crypto.provider.AmazonCorrettoCryptoProvider \
  --trace-object-instantiation=com.amazon.corretto.crypto.provider.Loader \
  --trace-class-initialization=com.amazon.corretto.crypto.provider.Loader \
  --trace-object-instantiation=com.amazon.corretto.crypto.provider.Janitor \
  --trace-class-initialization=com.amazon.corretto.crypto.provider.Janitor \
  --initialize-at-run-time=com.amazon.corretto.crypto.provider.AmazonCorrettoCryptoProvider

But I still get the error, without much information about where the instantiation is coming from:

Error: Detected a started Thread in the image heap. Threads running in the image generator are no longer running at image runtime.  Object has been initialized without the native-image initialization instrumentation and the stack trace can't be tracked. The object was probably created by a class initializer and is reachable from a static field. You can request class initialization at image runtime by using the option --initialize-at-run-time=<class-name>. Or you can write your own initialization methods and call them explicitly from your main entry point.
Detailed message:
Trace: Object was reached by 
        reading field java.util.concurrent.locks.AbstractOwnableSynchronizer.exclusiveOwnerThread of
                constant java.util.concurrent.locks.ReentrantLock$NonfairSync@3cf79d3a reached by 
        reading field java.util.concurrent.locks.ReentrantLock.sync of
                constant java.util.concurrent.locks.ReentrantLock@8f5c101 reached by 
------------------------------------------------------------------------------------------------------------------------
        reading field com.amazon.corretto.crypto.provider.Janitor$Stripe.queueLock of
                constant com.amazon.corretto.crypto.provider.Janitor$Stripe@56b712b7 reached by 
        indexing into array
                constant com.amazon.corretto.crypto.provider.Janitor$Stripe[]@79912746 reached by 
        reading field com.amazon.corretto.crypto.provider.Janitor$JanitorState.stripes of
                constant com.amazon.corretto.crypto.provider.Janitor$JanitorState@3cad4e7d reached by 
        scanning method com.amazon.corretto.crypto.provider.Janitor.register(Janitor.java:50)
Call path from entry point to com.amazon.corretto.crypto.provider.Janitor.register(Object, Runnable): 
        no path found from entry point to target method

What is calling Janitor.register() despite my removing the service loading?

@lestephane
Copy link
Author

lestephane commented Mar 16, 2022

Ah, I see in your module-info.class another class that may be loaded:

module com.amazon.corretto.crypto.provider {
    requires java.logging;
    exports com.amazon.corretto.crypto.provider;
    provides java.security.Provider with com....ServiceProviderFactory; << ---- HERE!!!
}

I now tried with native-image.properties:

Args=-H:ResourceConfigurationResources=${.}/resource-config.json \
  --initialize-at-run-time=com.amazon.corretto.crypto.provider.AmazonCorrettoCryptoProvider \
  --initialize-at-run-time=com.amazon.corretto.crypto.provider.ServiceProviderFactory

and resource-config.json containing:

{
  "resources":{
  "includes":[
    {
      "pattern":"\\Qcom/amazon/corretto/crypto/provider/libamazonCorrettoCryptoProvider.so\\E"
    }, 
    {
      "pattern":"\\Qcom/amazon/corretto/crypto/provider/testdata/ctr-drbg.txt\\E"
    }, 
    {
      "pattern":"\\Qcom/amazon/corretto/crypto/provider/testdata/hmac.txt\\E"
    }, 
    {
      "pattern":"\\Qcom/amazon/corretto/crypto/provider/version.properties\\E"
    }
  ]},
  "bundles":[]
}

Same error:

Error: Detected a started Thread in the image heap. Threads running in the image generator are no longer running at image runtime.  Object has been initialized without the native-image initialization instrumentation and the stack trace can't be tracked. The object was probably created by a class initializer and is reachable from a static field. You can request class initialization at image runtime by using the option --initialize-at-run-time=<class-name>. Or you can write your own initialization methods and call them explicitly from your main entry point.
Detailed message:
Trace: Object was reached by 
        reading field java.util.concurrent.locks.AbstractOwnableSynchronizer.exclusiveOwnerThread of
                constant java.util.concurrent.locks.ReentrantLock$NonfairSync@776014b reached by 
        reading field java.util.concurrent.locks.ReentrantLock.sync of
------------------------------------------------------------------------------------------------------------------------
                constant java.util.concurrent.locks.ReentrantLock@52baf25d reached by 
        reading field com.amazon.corretto.crypto.provider.Janitor$Stripe.queueLock of
                constant com.amazon.corretto.crypto.provider.Janitor$Stripe@4e64f639 reached by 
        indexing into array
                constant com.amazon.corretto.crypto.provider.Janitor$Stripe[]@550d0d22 reached by 
        reading field com.amazon.corretto.crypto.provider.Janitor$JanitorState.stripes of
                constant com.amazon.corretto.crypto.provider.Janitor$JanitorState@4a5c8852 reached by 
        scanning method com.amazon.corretto.crypto.provider.Janitor.register(Janitor.java:50)
Call path from entry point to com.amazon.corretto.crypto.provider.Janitor.register(Object, Runnable): 
        no path found from entry point to target method

@lestephane
Copy link
Author

lestephane commented Mar 16, 2022

latest update (and last one for a while):

native-image.properties

Args=\
  --initialize-at-run-time=com.amazon.corretto.crypto.provider \
  --trace-class-initialization=com.amazon.corretto.crypto.provider.AmazonCorrettoCryptoProvider \
  --trace-class-initialization=com.amazon.corretto.crypto.provider.Loader \
  -H:+TraceSecurityServices \
  -H:ReflectionConfigurationResources=${.}/reflect-config.json \
  -H:ResourceConfigurationResources=${.}/resource-config.json

reflect-config.json

[
{
  "name":"com.amazon.corretto.crypto.provider.AesCtrDrbg$SPI",
  "methods":[{"name":"<init>","parameterTypes":[] }]
},
{
  "name":"com.amazon.corretto.crypto.provider.AesGcmSpi",
  "methods":[{"name":"<init>","parameterTypes":[] }]
},
{
  "name":"com.amazon.corretto.crypto.provider.EcGen",
  "methods":[{"name":"<init>","parameterTypes":["com.amazon.corretto.crypto.provider.AmazonCorrettoCryptoProvider"] }]
},
{
  "name":"com.amazon.corretto.crypto.provider.EvpKeyAgreement$DH",
  "methods":[{"name":"<init>","parameterTypes":["com.amazon.corretto.crypto.provider.AmazonCorrettoCryptoProvider"] }]
},
{
  "name":"com.amazon.corretto.crypto.provider.EvpKeyAgreement$ECDH",
  "methods":[{"name":"<init>","parameterTypes":["com.amazon.corretto.crypto.provider.AmazonCorrettoCryptoProvider"] }]
},
{
  "name":"com.amazon.corretto.crypto.provider.EvpSignatureBase",
  "methods":[
    {"name":"setAlgorithmName","parameterTypes":["java.lang.String"] }
  ]
},
{
  "name":"com.amazon.corretto.crypto.provider.EvpSignature$SHA1withDSA",
  "methods":[
    {"name":"<init>","parameterTypes":["com.amazon.corretto.crypto.provider.AmazonCorrettoCryptoProvider"] },
    {"name":"setAlgorithmName","parameterTypes":["java.lang.String"] }
  ]
},
{
  "name":"com.amazon.corretto.crypto.provider.EvpSignature$SHA1withECDSA",
  "methods":[
    {"name":"<init>","parameterTypes":["com.amazon.corretto.crypto.provider.AmazonCorrettoCryptoProvider"] }, 
    {"name":"setAlgorithmName","parameterTypes":["java.lang.String"] }
  ]
},
{
  "name":"com.amazon.corretto.crypto.provider.EvpSignature$SHA1withRSA",
  "methods":[
    {"name":"<init>","parameterTypes":["com.amazon.corretto.crypto.provider.AmazonCorrettoCryptoProvider"] }, 
    {"name":"setAlgorithmName","parameterTypes":["java.lang.String"] }
  ]
},
{
  "name":"com.amazon.corretto.crypto.provider.EvpSignature$SHA224withDSA",
  "methods":[
    {"name":"<init>","parameterTypes":["com.amazon.corretto.crypto.provider.AmazonCorrettoCryptoProvider"] }, 
    {"name":"setAlgorithmName","parameterTypes":["java.lang.String"] }
  ]
},
{
  "name":"com.amazon.corretto.crypto.provider.EvpSignature$SHA224withECDSA",
  "methods":[
    {"name":"<init>","parameterTypes":["com.amazon.corretto.crypto.provider.AmazonCorrettoCryptoProvider"] }, 
    {"name":"setAlgorithmName","parameterTypes":["java.lang.String"] }
  ]
},
{
  "name":"com.amazon.corretto.crypto.provider.EvpSignature$SHA224withRSA",
  "methods":[
    {"name":"<init>","parameterTypes":["com.amazon.corretto.crypto.provider.AmazonCorrettoCryptoProvider"] }, 
    {"name":"setAlgorithmName","parameterTypes":["java.lang.String"] }
  ]
},
{
  "name":"com.amazon.corretto.crypto.provider.EvpSignature$SHA256withDSA",
  "methods":[
    {"name":"<init>","parameterTypes":["com.amazon.corretto.crypto.provider.AmazonCorrettoCryptoProvider"] }, 
    {"name":"setAlgorithmName","parameterTypes":["java.lang.String"] }
  ]
},
{
  "name":"com.amazon.corretto.crypto.provider.EvpSignature$SHA256withECDSA",
  "methods":[
    {"name":"<init>","parameterTypes":["com.amazon.corretto.crypto.provider.AmazonCorrettoCryptoProvider"] }, 
    {"name":"setAlgorithmName","parameterTypes":["java.lang.String"] }
  ]
},
{
  "name":"com.amazon.corretto.crypto.provider.EvpSignature$SHA256withRSA",
  "methods":[
    {"name":"<init>","parameterTypes":["com.amazon.corretto.crypto.provider.AmazonCorrettoCryptoProvider"] }, 
    {"name":"setAlgorithmName","parameterTypes":["java.lang.String"] }
  ]
},
{
  "name":"com.amazon.corretto.crypto.provider.EvpSignature$SHA384withDSA",
  "methods":[
    {"name":"<init>","parameterTypes":["com.amazon.corretto.crypto.provider.AmazonCorrettoCryptoProvider"] }, 
    {"name":"setAlgorithmName","parameterTypes":["java.lang.String"] }
  ]
},
{
  "name":"com.amazon.corretto.crypto.provider.EvpSignature$SHA384withECDSA",
  "methods":[
    {"name":"<init>","parameterTypes":["com.amazon.corretto.crypto.provider.AmazonCorrettoCryptoProvider"] }, 
    {"name":"setAlgorithmName","parameterTypes":["java.lang.String"] }
  ]
},
{
  "name":"com.amazon.corretto.crypto.provider.EvpSignature$SHA384withRSA",
  "methods":[
    {"name":"<init>","parameterTypes":["com.amazon.corretto.crypto.provider.AmazonCorrettoCryptoProvider"] }, 
    {"name":"setAlgorithmName","parameterTypes":["java.lang.String"] }
  ]
},
{
  "name":"com.amazon.corretto.crypto.provider.EvpSignature$SHA512withDSA",
  "methods":[
    {"name":"<init>","parameterTypes":["com.amazon.corretto.crypto.provider.AmazonCorrettoCryptoProvider"] }, 
    {"name":"setAlgorithmName","parameterTypes":["java.lang.String"] }
  ]
},
{
  "name":"com.amazon.corretto.crypto.provider.EvpSignature$SHA512withECDSA",
  "methods":[
    {"name":"<init>","parameterTypes":["com.amazon.corretto.crypto.provider.AmazonCorrettoCryptoProvider"] }, 
    {"name":"setAlgorithmName","parameterTypes":["java.lang.String"] }
  ]
},
{
  "name":"com.amazon.corretto.crypto.provider.EvpSignature$SHA512withRSA",
  "methods":[
    {"name":"<init>","parameterTypes":["com.amazon.corretto.crypto.provider.AmazonCorrettoCryptoProvider"] }, 
    {"name":"setAlgorithmName","parameterTypes":["java.lang.String"] }
  ]
},
{
  "name":"com.amazon.corretto.crypto.provider.EvpSignatureRaw$NONEwithDSA",
  "methods":[
    {"name":"<init>","parameterTypes":["com.amazon.corretto.crypto.provider.AmazonCorrettoCryptoProvider"] }, 
    {"name":"setAlgorithmName","parameterTypes":["java.lang.String"] }
  ]
},
{
  "name":"com.amazon.corretto.crypto.provider.EvpSignatureRaw$NONEwithECDSA",
  "methods":[
    {"name":"<init>","parameterTypes":["com.amazon.corretto.crypto.provider.AmazonCorrettoCryptoProvider"] }, 
    {"name":"setAlgorithmName","parameterTypes":["java.lang.String"] }
  ]
},
{
  "name":"com.amazon.corretto.crypto.provider.HmacMD5Spi",
  "methods":[{"name":"<init>","parameterTypes":[] }]
},
{
  "name":"com.amazon.corretto.crypto.provider.HmacSHA1Spi",
  "methods":[{"name":"<init>","parameterTypes":[] }]
},
{
  "name":"com.amazon.corretto.crypto.provider.HmacSHA256Spi",
  "methods":[{"name":"<init>","parameterTypes":[] }]
},
{
  "name":"com.amazon.corretto.crypto.provider.HmacSHA384Spi",
  "methods":[{"name":"<init>","parameterTypes":[] }]
},
{
  "name":"com.amazon.corretto.crypto.provider.HmacSHA512Spi",
  "methods":[{"name":"<init>","parameterTypes":[] }]
},
{
  "name":"com.amazon.corretto.crypto.provider.MD5Spi",
  "methods":[{"name":"<init>","parameterTypes":[] }]
},
{
  "name":"com.amazon.corretto.crypto.provider.RsaCipher$NoPadding",
  "methods":[{"name":"<init>","parameterTypes":["com.amazon.corretto.crypto.provider.AmazonCorrettoCryptoProvider"] }]
},
{
  "name":"com.amazon.corretto.crypto.provider.RsaCipher$OAEPSha1",
  "methods":[{"name":"<init>","parameterTypes":["com.amazon.corretto.crypto.provider.AmazonCorrettoCryptoProvider"] }]
},
{
  "name":"com.amazon.corretto.crypto.provider.RsaCipher$Pkcs1",
  "methods":[{"name":"<init>","parameterTypes":["com.amazon.corretto.crypto.provider.AmazonCorrettoCryptoProvider"] }]
},
{
  "name":"com.amazon.corretto.crypto.provider.RsaGen",
  "methods":[{"name":"<init>","parameterTypes":["com.amazon.corretto.crypto.provider.AmazonCorrettoCryptoProvider"] }]
},
{
  "name":"com.amazon.corretto.crypto.provider.SHA1Spi",
  "methods":[{"name":"<init>","parameterTypes":[] }]
},
{
  "name":"com.amazon.corretto.crypto.provider.SHA256Spi",
  "methods":[{"name":"<init>","parameterTypes":[] }]
},
{
  "name":"com.amazon.corretto.crypto.provider.SHA384Spi",
  "methods":[{"name":"<init>","parameterTypes":[] }]
},
{
  "name":"com.amazon.corretto.crypto.provider.SHA512Spi",
  "methods":[{"name":"<init>","parameterTypes":[] }]
}
]

resource-config.json

{
  "resources":{
  "includes":[
    {
      "pattern":"\\Qcom/amazon/corretto/crypto/provider/libamazonCorrettoCryptoProvider.so\\E"
    }, 
    {
      "pattern":"\\Qcom/amazon/corretto/crypto/provider/testdata/ctr-drbg.txt\\E"
    }, 
    {
      "pattern":"\\Qcom/amazon/corretto/crypto/provider/testdata/hmac.txt\\E"
    }, 
    {
      "pattern":"\\Qcom/amazon/corretto/crypto/provider/version.properties\\E"
    }
  ]},
  "bundles":[]
}

build.gradle.kts

This strips the signatures from your artifact, so that GraalVM may consume the config jsons above from another part of the classpath without SecurityException. If you add the config json files above to the META-INF/native-image of your project, this won't be necessary anymore.

plugins {
    ...
    id("org.graalvm.buildtools.native")
}

dependencies {
    api("software.amazon.cryptools:AmazonCorrettoCryptoProvider:1.+:linux-x86_64")
}

tasks.jar {
    println("creating crypto jar without signatures")
    from(configurations.compileClasspath.get().map {
        if (it.isDirectory) { it } else { zipTree(it) }) {
        exclude("META-INF/*.SF")
        exclude("META-INF/*.DSA")
        exclude("META-INF/*.RSA")
        exclude("META-INF/module-info.class")  // prevent service loading
        exclude("META-INF/services/*")              // prevent service loading
    }
}

graalvmNative {
    binaries {
        named("main") {
            sharedLibrary.set(false)
            mainClass.set("repro.InstallKt")
            buildArgs(
                "--no-fallback",
                "-H:+ReportExceptionStackTraces",
                "-H:+ReportUnsupportedElementsAtRuntime",
                "--allow-incomplete-classpath",
            )
            jvmArgs.add("-verbose:class")
        }
    }
}

repro.InstallKt

package repro

import com.amazon.corretto.crypto.provider.AmazonCorrettoCryptoProvider

fun main() {
    AmazonCorrettoCryptoProvider.install()
    AmazonCorrettoCryptoProvider.INSTANCE.assertHealthy()
}

java.security (in JAVA_HOME)

taken from your project

#
# List of providers and their preference orders

# Note that we can't just insert ours at the top - we need to restate all
# providers that are being shifted down to a different index (which is to say,
# all of them).
#
# Also, JDK9+ handles this list very differently from JDK8.
# JDK8 requires that providers be specified using fully-qualified class names.
# JDK9+ supports fully-qualified class names if and only if the module containing the class exports it.
# For modules which don't export the class in question, the provider must be specified used its "Provider Name".
# Many of the providers which come as part of the JDK (e.g., SunEC) are not exported from their modules and
# thus must be specified using their Provider Name rather than their class name.
#
# This means that for most of these providers there is no single way to specify them which works for both JDK8 and JDK9+.
#
# Rather than have two different copies of this file (one for JDK8 and one for JDK9+) which users must select between
# depending on which JDK8 they are running, we have created a single merged listing.
# ACCP is listed first as a fully-qualified class (because it is exported by the module and will work on all systems).
# After that we alternate between the fully-qualified class (for JDK8) and the provider name for those which
# are not exported by the module for JDK9+.
# Each JDK will ignore entries it doesn't understand.
# JDK8 will determine that there is no class with the short provider name and skip it.
# JDK9+ will determine that the fully-qualified class is not visible and will skip it.
#
# This results in a single list with proper behavior on both JDK8 and JDK9+ systems.
#

security.provider.1=com.amazon.corretto.crypto.provider.AmazonCorrettoCryptoProvider
security.provider.2=sun.security.provider.Sun
security.provider.3=sun.security.rsa.SunRsaSign
security.provider.4=sun.security.ec.SunEC
security.provider.5=SunEC
security.provider.6=com.sun.net.ssl.internal.ssl.Provider
security.provider.7=com.sun.crypto.provider.SunJCE
security.provider.8=sun.security.jgss.SunProvider
security.provider.9=SunJGSS
security.provider.10=com.sun.security.sasl.Provider
security.provider.11=SunSASL
security.provider.12=org.jcp.xml.dsig.internal.dom.XMLDSigRI
security.provider.13=XMLDSig
security.provider.14=sun.security.smartcardio.SunPCSC
security.provider.15=SunPCSC
security.provider.16=JdkLDAP
security.provider.17=JdkSASL
security.provider.18=SunPKCS11

#
# A list of known strong SecureRandom implementations.
#
# To help guide applications in selecting a suitable strong
# java.security.SecureRandom implementation, Java distributions should
# indicate a list of known strong implementations using the property.
#
# This is a comma-separated list of algorithm and/or algorithm:provider
# entries.
#
securerandom.strongAlgorithms=NIST800-90A/AES-CTR-256:AmazonCorrettoCryptoProvider,NativePRNGBlocking:SUN,DRBG:SUN

Result

$ ./gradlew :project:nativeRun


Error: Classes that should be initialized at run time got initialized during image building:
 com.amazon.corretto.crypto.provider.Loader the class was requested to be initialized at run time (from jar:file:///project/awssdkclient/cryptoprovider/build/libs/awssdkclient-cryptoprovider.jar!/META-INF/native-image/software.amazon.cryptools/AmazonCorrettoCryptoProvider/native-image.properties with 'com.amazon.corretto.crypto.provider'). com.amazon.corretto.crypto.provider.Loader 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 com.amazon.corretto.crypto.provider.Loader
com.amazon.corretto.crypto.provider.AmazonCorrettoCryptoProvider the class was requested to be initialized at run time (from jar:file:///project/awssdkclient/cryptoprovider/build/libs/awssdkclient-cryptoprovider.jar!/META-INF/native-image/software.amazon.cryptools/AmazonCorrettoCryptoProvider/native-image.properties with 'com.amazon.corretto.crypto.provider'). To see why com.amazon.corretto.crypto.provider.AmazonCorrettoCryptoProvider got initialized use --trace-class-initialization=com.amazon.corretto.crypto.provider.AmazonCorrettoCryptoProvider

...

        at com.oracle.svm.core.util.UserError.abort(UserError.java:73)
        at com.oracle.svm.hosted.classinitialization.ConfigurableClassInitialization.checkDelayedInitialization(ConfigurableClassInitialization.java:555)
        at com.oracle.svm.hosted.classinitialization.ClassInitializationFeature.duringAnalysis(ClassInitializationFeature.java:167)
        at com.oracle.svm.hosted.NativeImageGenerator.lambda$runPointsToAnalysis$10(NativeImageGenerator.java:704)
------------------------------------------------------------------------------------------------------------------------
        at com.oracle.svm.hosted.FeatureHandler.forEachFeature(FeatureHandler.java:74)
        at com.oracle.svm.hosted.NativeImageGenerator.lambda$runPointsToAnalysis$11(NativeImageGenerator.java:704)
        at com.oracle.graal.pointsto.PointsToAnalysis.runAnalysis(PointsToAnalysis.java:755)
        at com.oracle.svm.hosted.NativeImageGenerator.runPointsToAnalysis(NativeImageGenerator.java:702)
        at com.oracle.svm.hosted.NativeImageGenerator.doRun(NativeImageGenerator.java:537)
        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)

I've spent all the time I'll be able to spare on this problem. In the end, Amazon is better placed to make the provider plug and play for GraalVM, which will help a lot of people.

@lestephane lestephane changed the title AmazonCorrettoCryptoProvider.install() early at startup causes graalvm native-image to complain when --initialize-at-build-time is in use Unable to use AmazonCorrettoCryptoProvider with GraalVM native-image Mar 16, 2022
@SalusaSecondus
Copy link
Contributor

Absolutely. The solution to something like this should rest with us.

Thank you so much for the work and research you did above. I'm sorry that the solution wasn't something quick and easy. We hear the need for this and will try to get some eyes on it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

2 participants