Quarkus: Native compilation fails with MP Rest Client

Created on 13 Oct 2020  路  19Comments  路  Source: quarkusio/quarkus

See also https://quarkusio.zulipchat.com/#narrow/stream/187030-users/topic/Native.20and.20rest-client

Describe the bug

Create an app with the MP RestClient (or apparently also GraphQL client -- see https://quarkusio.zulipchat.com/#narrow/stream/187030-users/topic/graphql.20microprofile/near/198970978 )

then try to compile this to native

This ends up in something like

Caused by: com.oracle.graal.pointsto.constraints.UnsupportedFeatureException: No instances of sun.security.provider.NativePRNG are allowed in the image heap as this class should be initialized at image runtime. To see how this object got instantiated use -H:+TraceClassInitialization.
Detailed message:
Trace: Object was reached by
    reading field java.security.SecureRandom.secureRandomSpi of
        constant java.security.SecureRandom@4fa8cb4 reached by
    reading field sun.security.ssl.SSLContextImpl.secureRandom of
        constant sun.security.ssl.SSLContextImpl$TLSContext@67cd2da reached by
    reading field sun.security.ssl.SSLSocketFactoryImpl.context of
        constant sun.security.ssl.SSLSocketFactoryImpl@7c8befbb reached by
    reading field org.apache.http.conn.ssl.SSLConnectionSocketFactory.socketfactory of
        constant org.apache.http.conn.ssl.SSLConnectionSocketFactory@652a8d99 reached by
    reading field java.util.concurrent.ConcurrentHashMap$Node.val of
        constant java.util.concurrent.ConcurrentHashMap$Node@7e52f699 reached by
    indexing into array
        constant java.util.concurrent.ConcurrentHashMap$Node[]@31ebe5c5 reached by
    reading field java.util.concurrent.ConcurrentHashMap.table of
        constant java.util.concurrent.ConcurrentHashMap@2089b9a9 reached by
    reading field org.apache.http.config.Registry.map of
        constant org.apache.http.config.Registry@61ba6f03 reached by
    reading field org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.socketFactoryRegistry of
        constant org.apache.http.impl.conn.DefaultHttpClientConnectionOperator@1e443cae reached by
    reading field org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connectionOperator of
        constant org.apache.http.impl.conn.PoolingHttpClientConnectionManager@f07065f reached by
    reading field org.apache.http.impl.client.HttpClientBuilder$2.val$cm of
        constant org.apache.http.impl.client.HttpClientBuilder$2@544a1d92 reached by
    indexing into array
        constant java.lang.Object[]@34752250 reached by
    reading field java.util.ArrayList.elementData of
        constant java.util.ArrayList@4bf1b087 reached by
    reading field org.apache.http.impl.client.InternalHttpClient.closeables of
        constant org.apache.http.impl.client.InternalHttpClient@4c454c5 reached by
    reading field org.jboss.resteasy.client.jaxrs.engines.ManualClosingApacheHttpClient43Engine.httpClient of
        constant org.jboss.resteasy.client.jaxrs.engines.ApacheHttpClient43Engine@643e52f7 reached by
    reading field org.jboss.resteasy.client.jaxrs.internal.ResteasyClientImpl.httpEngine of
        constant org.jboss.resteasy.microprofile.client.impl.MpClient@165deefb reached by
    reading field org.jboss.resteasy.microprofile.client.ProxyInvocationHandler.client of
        constant org.jboss.resteasy.microprofile.client.ProxyInvocationHandler@432dfe97 reached by
    reading field java.lang.reflect.Proxy.h of
        constant com.sun.proxy.$Proxy338@392f433f reached by
    reading field com.redhat.cloud.policies.app.auth.RbacFilter.rbac of
        constant com.redhat.cloud.policies.app.auth.RbacFilter_Subclass@38e67950 reached by
    reading field org.jboss.resteasy.core.interception.jaxrs.JaxrsInterceptorRegistryImpl$OnDemandInterceptorFactory.interceptor of
        constant org.jboss.resteasy.core.interception.jaxrs.JaxrsInterceptorRegistryImpl$OnDemandInterceptorFactory@1a2c343c reached by
    indexing into array

Expected behavior

App can be compiled to native

This is with Quarkus 1.8.2

arenative-image arerest-client kinbug

Most helpful comment

Thanks @geoand, added to my todos :)

All 19 comments

/cc @phillip-kruger

Same problem exists in 1.10.0.Final

Caused by: com.oracle.graal.pointsto.constraints.UnsupportedFeatureException: No instances of sun.security.provider.NativePRNG are allowed in the image heap as this class should be initialized at image runtime. To see how this object got instantiated use --trace-object-instantiation=sun.security.provider.NativePRNG.
Detailed message:
Trace: Object was reached by
    reading field java.security.SecureRandom.secureRandomSpi of
        constant java.security.SecureRandom@60e2425 reached by
    reading field sun.security.ssl.SSLContextImpl.secureRandom of
        constant sun.security.ssl.SSLContextImpl$TLSContext@6b5d19cf reached by
    reading field sun.security.ssl.SSLSocketFactoryImpl.context of
        constant sun.security.ssl.SSLSocketFactoryImpl@3d18c639 reached by
    reading field org.apache.http.conn.ssl.SSLConnectionSocketFactory.socketfactory of
        constant org.apache.http.conn.ssl.SSLConnectionSocketFactory@1726ceef reached by
    reading field java.util.concurrent.ConcurrentHashMap$Node.val of
        constant java.util.concurrent.ConcurrentHashMap$Node@466b91b reached by
    indexing into array
        constant java.util.concurrent.ConcurrentHashMap$Node[]@5eae4e26 reached by
    reading field java.util.concurrent.ConcurrentHashMap.table of
        constant java.util.concurrent.ConcurrentHashMap@46ab82a8 reached by
    reading field org.apache.http.config.Registry.map of
        constant org.apache.http.config.Registry@38e1fe46 reached by
    reading field org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.socketFactoryRegistry of
        constant org.apache.http.impl.conn.DefaultHttpClientConnectionOperator@4ccf48a0 reached by
    reading field org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connectionOperator of
        constant org.apache.http.impl.conn.PoolingHttpClientConnectionManager@5714a15f reached by
    reading field org.apache.http.impl.client.HttpClientBuilder$2.val$cm of
        constant org.apache.http.impl.client.HttpClientBuilder$2@793410dd reached by
    indexing into array
        constant java.lang.Object[]@5bc84d20 reached by
    reading field java.util.ArrayList.elementData of
        constant java.util.ArrayList@4268f9f0 reached by
    reading field org.apache.http.impl.client.InternalHttpClient.closeables of
        constant org.apache.http.impl.client.InternalHttpClient@56b30498 reached by
    reading field org.jboss.resteasy.client.jaxrs.engines.ManualClosingApacheHttpClient43Engine.httpClient of
        constant org.jboss.resteasy.client.jaxrs.engines.ApacheHttpClient43Engine@62293a5d reached by
    reading field org.jboss.resteasy.client.jaxrs.internal.ResteasyClientImpl.httpEngine of
        constant org.jboss.resteasy.microprofile.client.impl.MpClient@b2447fe reached by
    reading field org.jboss.resteasy.microprofile.client.ProxyInvocationHandler.client of
        constant org.jboss.resteasy.microprofile.client.ProxyInvocationHandler@270331c8 reached by

I am able to force the MP Rest client to use the URLConnection instead of Apache http client with below configuration. It took me hours to figure this out, would be helpful if we add this in the Quarkus Rest Client documentation until we find a permanent fix for Apache Http Client in native mode

quarkus.native.additional-build-args =\
    -H:EnableURLProtocols=https,\
    -J-Dorg.jboss.resteasy.microprofile.defaultToURLConnectionHttpClient=true

@missourian55 any chance you could share a small reproducer?

@geoand I'm surprised the Apache HTTP client doesn't work in native? I would have thought we had fixed that for ages.

The Apache HTTP client should work in native.
We use it in some extensions without issue (in the spring cloud config extension for example).

@gsmet

Here is the reproducer, I used Quarkus S3 guide as the base and added other required extensions

Steps to reproduce:

  1. Clone the repo https://github.com/missourian55/s3-demo.git
  2. Execute this native build
    ./mvnw clean package -Pnative -Dnative-image.docker-build=true -Dquarkus.container-image.build=true -Dnative-image.xmx=6g
  3. You will see below stacktrace at build time
Caused by: com.oracle.graal.pointsto.constraints.UnsupportedFeatureException: No instances of sun.security.provider.NativePRNG are allowed in the image heap as this class should be initialized at image runtime. To see how this object got instantiated use -H:+TraceClassInitialization.
Detailed message:
Trace: Object was reached by
    reading field java.security.SecureRandom.secureRandomSpi of
        constant java.security.SecureRandom@503562f4 reached by
    reading field sun.security.ssl.SSLContextImpl.secureRandom of
        constant sun.security.ssl.SSLContextImpl$TLSContext@668c6f89 reached by
    reading field sun.security.ssl.SSLSocketFactoryImpl.context of
        constant sun.security.ssl.SSLSocketFactoryImpl@33ebc721 reached by
    reading field org.apache.http.conn.ssl.SSLConnectionSocketFactory.socketfactory of
        constant org.apache.http.conn.ssl.SSLConnectionSocketFactory@4d9c51c7 reached by
    reading field java.util.concurrent.ConcurrentHashMap$Node.val of
  1. Add below property to the application.properties and execute the build and notice build success
quarkus.native.additional-build-args =\
    -J-Dorg.jboss.resteasy.microprofile.defaultToURLConnectionHttpClient=true

Thanks in advance.

I'll take a look

@geoand I reported the issue with https://github.com/RedHatInsights/policies-ui-backend
I did create a small reproducer at https://github.com/pilhuhn/quarkus-rest-json-quickstart which compiles to native on rhel8 (but fails to link).
So there must be more involved than purely the rest-client

@pilhuhn using your reproducer I couldn't reproduce a problem (on Ubuntu), so if there is an issue, it's probably different than the original issue

This is what I tried to say - the minimal reproducer does not show the issue, so it must be something different in the larger context of the policy-ui-backend.
Did the minimal one link (so completely succeed)? If so, I'll open a new issue for that.

Cool, thanks

I tried the reproducer that @missourian55 linked and could indeed reproduce the problem.

There appears to be an easy solution which is to add:

quarkus.native.additional-build-args=--rerun-class-initialization-at-runtime=sun.security.provider.NativePRNG

I think it makes for the quarkus-rest-client extension to force reinitialization of this class (thus removing the burden from the user application), but I would to like to hear what @gsmet and @galderz think.

Given it's a very common issue, if it's a valid workaround, I would even do it in Core. But I'm not sure of all the consequences.

Let's wait for @galderz 's opinion.

/cc @dmlloyd too

@geoand Thanks I have tried the workaround, is it safe to ignore this warning?

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.

@missourian55 yes, it is safe to ignore that warning. If we provide the support on our side eventually, that warning won't be present at all.

@gsmet @geoand The workaround might work but I feel it's hiding the real issue: why is SSL connection factory being created a cached? Seems to me something like that should be done at runtime... which if you follow back to the top, the question is, why is the HTTP client be initialised at image build time? Does it make sense to make such a thing at image build time? I feel that's the real issue to fix, avoid initialising things that really should be initialised at runtime. Connections (e.g. netty, http clients and similar) and security are things for which the majority of work should be done at runtime.

That is probably right, but I am not very familiar with the implementation of the client.

@michalszynkiewicz care to take a look at this one?

Thanks @geoand, added to my todos :)

In @pilhuhn 's project, the problem seems to occur only if the RbacFilter (a ContainerRequestFilter) is injecting a rest client stub.
Digging deeper :pick:

Was this page helpful?
0 / 5 - 0 ratings