35

I've got a dropwizard app, which runs fine with the standard JRE.

I've tried creating a runtime using jlink which is considerably smaller:

/Library/Java/JavaVirtualMachines/jdk-11.jdk/Contents/Home/bin/jlink --no-header-files --no-man-pages --compress=2 --strip-debug --add-modules java.base,java.compiler,java.desktop,java.instrument,java.logging,java.management,java.naming,java.scripting,java.security.jgss,java.sql,java.xml,jdk.attach,jdk.jdi,jdk.management,jdk.unsupported --output jre

If I run it with the jlink created runtime it throws this error connecting to redis (which has stunnel in front of it).

ERROR [2019-03-31 09:12:20,080] com.company.project.core.WorkerThread: Failed to process message.
! javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
! at java.base/sun.security.ssl.Alert.createSSLException(Unknown Source)
! at java.base/sun.security.ssl.Alert.createSSLException(Unknown Source)
! at java.base/sun.security.ssl.TransportContext.fatal(Unknown Source)
! at java.base/sun.security.ssl.Alert$AlertConsumer.consume(Unknown Source)
! at java.base/sun.security.ssl.TransportContext.dispatch(Unknown Source)
! at java.base/sun.security.ssl.SSLTransport.decode(Unknown Source)
! at java.base/sun.security.ssl.SSLSocketImpl.decode(Unknown Source)
! at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(Unknown Source)
! at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
! at java.base/sun.security.ssl.SSLSocketImpl.ensureNegotiated(Unknown Source)
! at java.base/sun.security.ssl.SSLSocketImpl$AppOutputStream.write(Unknown Source)
! at redis.clients.jedis.util.RedisOutputStream.flushBuffer(RedisOutputStream.java:52)
! at redis.clients.jedis.util.RedisOutputStream.flush(RedisOutputStream.java:133)
! at redis.clients.jedis.Connection.flush(Connection.java:300)
! ... 9 common frames omitted
! Causing: redis.clients.jedis.exceptions.JedisConnectionException: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
! at redis.clients.jedis.Connection.flush(Connection.java:303)
! at redis.clients.jedis.Connection.getStatusCodeReply(Connection.java:235)
! at redis.clients.jedis.BinaryJedis.auth(BinaryJedis.java:2225)
! at redis.clients.jedis.JedisFactory.makeObject(JedisFactory.java:119)
! at org.apache.commons.pool2.impl.GenericObjectPool.create(GenericObjectPool.java:888)
! at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:432)
! at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:361)
! at redis.clients.jedis.util.Pool.getResource(Pool.java:50)
! ... 2 common frames omitted
! Causing: redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
! at redis.clients.jedis.util.Pool.getResource(Pool.java:59)
! at redis.clients.jedis.JedisPool.getResource(JedisPool.java:234)

The stunnel server logs show:

redis_1  | 09:12:20 stunnel.1 | 2019.03.31 09:12:20 LOG7[23]: TLS alert (write): fatal: handshake failure
redis_1  | 09:12:20 stunnel.1 | 2019.03.31 09:12:20 LOG3[23]: SSL_accept: 141F7065: error:141F7065:SSL routines:final_key_share:no suitable key share
redis_1  | 09:12:20 stunnel.1 | 2019.03.31 09:12:20 LOG5[23]: Connection reset: 0 byte(s) sent to TLS, 0 byte(s) sent to socket

Are there some crypt algorithms being left out by jlink?

rich
  • 18,987
  • 11
  • 75
  • 101
  • 9
    Hmmn. If I add jdk.crypto.ec it works - why would jdeps have left that one out, if that one, would there be any others it's left out? – rich Mar 31 '19 at 09:45
  • 3
    I seem to recall that JCA providers are extensions: nothing in the library depends directly on them, they must be put into the classpath explicitly (like other typical adapter extensions: database connectors, etc) – jjmontes Mar 31 '19 at 09:50
  • That's why modules are a pain in the back – Kowlown Jun 16 '22 at 13:15

3 Answers3

45

As rich mentions in a comment

Hmmn. If I add jdk.crypto.ec it works - why would jdeps have left that one out, if that one, would there be any others it's left out?

adding jdk.crypto.ec to the modules list solved the problem.

Bhargav Rao
  • 50,140
  • 28
  • 121
  • 140
Djowin
  • 466
  • 5
  • 4
  • 5
    So you can jlink a perfectly good runtime with HTTPS support, but without any SSL/TLS/... implementation and only notice when the handshake fails with an error message that is... obfuscating. I get why this happens, but it is certainly not convenient nor following the principle of least surprise. – Hendrik Oct 03 '19 at 16:18
  • 5
    This is extremely frustrating, this was the fix. I had my app deployed for months on a JRE and then it suddenly lost ability to talk to my server (which means no updates). Why would they not just include this. – Mgamerz Jan 25 '20 at 17:56
  • 1
    On OpenJDK11.0.9/Win64 this icreases the JRE size by `0.3 MiB`. – lapo Oct 23 '20 at 13:46
  • Noting for search engines that it also fixes the error `Received fatal alert: access_denied` – Asapha Sep 02 '21 at 09:28
  • This is why anytime I want to start a project in Java I should remind myself that it'll take me 14 hours to find the hidden treasures of fuckery. Thank you so much for this answer, it saved me, and helped me realize this is the last Java based project I'm ever doing for work. – smerkd Sep 07 '22 at 01:39
9

One could also just add --bind-services (Link in service provider modules and their dependences) to the jlink command. But according to my experience this will make the resulting runtime much bigger. But at least this is an option to quickly find out whether observed problems are due to a missing Service implementation.

mipa
  • 10,369
  • 2
  • 16
  • 35
3

I had to add jdk.crypto.ec and jdk.crypto.cryptoki as well.

rednoah
  • 1,053
  • 14
  • 41