The OkHttpClient.Builder has a deprecated method to inject SSLSocketFactory: OkHttpClient.Builder#sslSocketFactory(SSLSocketFactory)
This method is fetching the X509TrustManager via reflection.
This is not supported on Java 9+ (I guess JPMS restricts it).
From Java 8u252 (8u242 is fine), the Jdk9Platform is picked because the logic which picks the right platform is based on checking if certain methods exist via reflection and those methods were backported into Java 8 from 8u252: Jdk9Platform.java#L92-L94. This breaks the OkHttpClient.Builder#sslSocketFactory(SSLSocketFactory), it always throws an exception on 8u252.
Here is SSLParameters#setApplicationProtocols(String[]) in 8u252
While 8u242 does not contain it
And here is SSLSocket#getApplicationProtocol() in 8u252
While 8u242 does not contain it
Here's a test suite to demo the issue:
- Both cases are ok on java 8u242
- The first one (
shouldCreateTheClientWithoutTheTrustManager) fails on 8u252
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
import okhttp3.OkHttpClient;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertNotNull;
class OkHttpJavaDetectionTest {
@Test
void shouldCreateTheClientWithoutTheTrustManager() throws NoSuchAlgorithmException {
OkHttpClient client = new OkHttpClient.Builder()
.sslSocketFactory(SSLContext.getDefault().getSocketFactory())
.build();
assertNotNull(client);
}
@Test
void shouldCreateTheClientWitTheTrustManager() throws NoSuchAlgorithmException, KeyStoreException {
OkHttpClient client = new OkHttpClient.Builder()
.sslSocketFactory(SSLContext.getDefault().getSocketFactory(), createTrustManager())
.build();
assertNotNull(client);
}
private X509TrustManager createTrustManager() throws NoSuchAlgorithmException, KeyStoreException {
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init((KeyStore) null);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
throw new IllegalStateException("Unexpected default trust managers: " + Arrays.toString(trustManagers));
}
return (X509TrustManager) trustManagers[0];
}
}
Here's the relevant section of the stacktrace:
java.lang.UnsupportedOperationException: clientBuilder.sslSocketFactory(SSLSocketFactory) not supported on JDK 9+
at okhttp3.internal.platform.Jdk9Platform.trustManager(Jdk9Platform.java:77)
at okhttp3.internal.platform.Platform.buildCertificateChainCleaner(Platform.java:177)
at okhttp3.OkHttpClient$Builder.sslSocketFactory(OkHttpClient.java:743)
...
The
OkHttpClient.Builderhas a deprecated method to injectSSLSocketFactory:OkHttpClient.Builder#sslSocketFactory(SSLSocketFactory)This method is fetching the
X509TrustManagervia reflection.This is not supported on Java 9+ (I guess JPMS restricts it).
From Java
8u252(8u242is fine), theJdk9Platformis picked because the logic which picks the right platform is based on checking if certain methods exist via reflection and those methods were backported into Java 8 from 8u252: Jdk9Platform.java#L92-L94. This breaks theOkHttpClient.Builder#sslSocketFactory(SSLSocketFactory), it always throws an exception on8u252.Here is
SSLParameters#setApplicationProtocols(String[])in8u252While
8u242does not contain itAnd here is
SSLSocket#getApplicationProtocol()in8u252While
8u242does not contain itHere's a test suite to demo the issue:
shouldCreateTheClientWithoutTheTrustManager) fails on 8u252Here's the relevant section of the stacktrace: