Skip to content

Commit 52480f1

Browse files
GH-742 - Fix native compilation with Netty 4.1.50 on GraalVM. (#743)
Netty 4.1.50 needs two fixes for in our setup for native compilation on GraalVM: * Remove substitutions for io.netty.handler.ssl.Java9SslEngine. as `io.netty.handler.ssl.Java9SslEngine` has been removed in Netty 4.1.50, Graal cannot substitute a class not on the classpath. * Remove the substitution for the task queue in the `io.netty.channel.nio.NioEventLoop` class. Thus, the JCTools Mpsc will be used instead. The Mpsc queues need a bit of reflection to work in native mode, but this is very isolated. Also, Netty upgraded to JCTools 3.0.0 in 4.1.46 and the Mpsc queues now are triggered during class initialition already, even with the substitution. So we should live with the bits of reflection in native mode and remove the somewhat brittle substitution along the way. Also it seems that the system property `io.netty.noUnsafe` which we set in the `native-image.properties` is not taken into account at all.
1 parent 6664215 commit 52480f1

File tree

2 files changed

+82
-19
lines changed

2 files changed

+82
-19
lines changed

driver/src/main/java/org/neo4j/driver/internal/svm/NettySubstitutions.java

Lines changed: 46 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,11 @@
2222
import com.oracle.svm.core.annotate.Substitute;
2323
import com.oracle.svm.core.annotate.TargetClass;
2424
import com.oracle.svm.core.jdk.JDK11OrLater;
25+
import com.oracle.svm.core.jdk.JDK8OrEarlier;
2526

2627
import java.security.PrivateKey;
2728
import java.security.Provider;
2829
import java.security.cert.X509Certificate;
29-
import java.util.Queue;
30-
import java.util.concurrent.LinkedBlockingDeque;
3130
import javax.net.ssl.KeyManagerFactory;
3231
import javax.net.ssl.SSLEngine;
3332
import javax.net.ssl.SSLException;
@@ -113,20 +112,58 @@ final class Target_io_netty_handler_ssl_SslHandler$SslEngineType {
113112
@TargetClass(className = "io.netty.handler.ssl.JdkAlpnApplicationProtocolNegotiator$AlpnWrapper", onlyWith = JDK11OrLater.class)
114113
final class Target_io_netty_handler_ssl_JdkAlpnApplicationProtocolNegotiator_AlpnWrapper {
115114
@Substitute
116-
@SuppressWarnings( "deprecation" )
117-
public SSLEngine wrapSslEngine( SSLEngine engine, ByteBufAllocator alloc,
115+
public SSLEngine wrapSslEngine(SSLEngine engine, ByteBufAllocator alloc,
116+
JdkApplicationProtocolNegotiator applicationNegotiator, boolean isServer) {
117+
return (SSLEngine) (Object) new Target_io_netty_handler_ssl_JdkAlpnSslEngine(engine, applicationNegotiator, isServer);
118+
}
119+
120+
}
121+
122+
@TargetClass(className = "io.netty.handler.ssl.JdkAlpnApplicationProtocolNegotiator$AlpnWrapper", onlyWith = JDK8OrEarlier.class)
123+
final class Target_io_netty_handler_ssl_JdkAlpnApplicationProtocolNegotiator_AlpnWrapperJava8 {
124+
@Substitute
125+
public SSLEngine wrapSslEngine(SSLEngine engine, ByteBufAllocator alloc,
118126
JdkApplicationProtocolNegotiator applicationNegotiator, boolean isServer) {
119-
return (SSLEngine) (Object) new Target_io_netty_handler_ssl_Java9SslEngine(
120-
engine, applicationNegotiator, isServer);
127+
if (Target_io_netty_handler_ssl_JettyAlpnSslEngine.isAvailable()) {
128+
return isServer
129+
? (SSLEngine) (Object) Target_io_netty_handler_ssl_JettyAlpnSslEngine.newServerEngine(engine,
130+
applicationNegotiator)
131+
: (SSLEngine) (Object) Target_io_netty_handler_ssl_JettyAlpnSslEngine.newClientEngine(engine,
132+
applicationNegotiator);
133+
}
134+
throw new RuntimeException("Unable to wrap SSLEngine of type " + engine.getClass().getName());
121135
}
122136

123137
}
124138

125-
@TargetClass(className = "io.netty.handler.ssl.Java9SslEngine", onlyWith = JDK11OrLater.class)
126-
final class Target_io_netty_handler_ssl_Java9SslEngine {
139+
@TargetClass(className = "io.netty.handler.ssl.JettyAlpnSslEngine", onlyWith = JDK8OrEarlier.class)
140+
final class Target_io_netty_handler_ssl_JettyAlpnSslEngine {
141+
@Substitute
142+
static boolean isAvailable() {
143+
return false;
144+
}
145+
146+
@Substitute
147+
@SuppressWarnings( "deprecation" )
148+
static Target_io_netty_handler_ssl_JettyAlpnSslEngine newClientEngine(SSLEngine engine,
149+
JdkApplicationProtocolNegotiator applicationNegotiator) {
150+
return null;
151+
}
152+
153+
@Substitute
154+
@SuppressWarnings( "deprecation" )
155+
static Target_io_netty_handler_ssl_JettyAlpnSslEngine newServerEngine(SSLEngine engine,
156+
JdkApplicationProtocolNegotiator applicationNegotiator) {
157+
return null;
158+
}
159+
}
160+
161+
@TargetClass(className = "io.netty.handler.ssl.JdkAlpnSslEngine", onlyWith = JDK11OrLater.class)
162+
final class Target_io_netty_handler_ssl_JdkAlpnSslEngine {
163+
127164
@Alias
128165
@SuppressWarnings( "deprecation" )
129-
Target_io_netty_handler_ssl_Java9SslEngine(final SSLEngine engine,
166+
Target_io_netty_handler_ssl_JdkAlpnSslEngine(final SSLEngine engine,
130167
final JdkApplicationProtocolNegotiator applicationNegotiator, final boolean isServer) {
131168

132169
}
@@ -298,15 +335,5 @@ final ChannelFuture initAndRegister() {
298335
}
299336
}
300337

301-
@TargetClass(className = "io.netty.channel.nio.NioEventLoop")
302-
final class Target_io_netty_channel_nio_NioEventLoop {
303-
304-
@Substitute
305-
private static Queue<Runnable> newTaskQueue0(int maxPendingTasks) {
306-
return new LinkedBlockingDeque<>();
307-
}
308-
}
309-
310338
class NettySubstitutions {
311-
312339
}

driver/src/main/resources/META-INF/native-image/org.neo4j.driver/neo4j-java-driver/reflection-config.json

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,41 @@
1818
{
1919
"name" : "org.neo4j.driver.internal.shaded.io.netty.util.ReferenceCountUtil",
2020
"allDeclaredMethods" : true
21+
},
22+
{
23+
"name" : "org.neo4j.driver.internal.shaded.io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueProducerIndexField",
24+
"fields": [
25+
{"name": "producerIndex", "allowUnsafeAccess": true}
26+
]
27+
},
28+
{
29+
"name" : "org.neo4j.driver.internal.shaded.io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueProducerLimitField",
30+
"fields": [
31+
{"name": "producerLimit", "allowUnsafeAccess": true}
32+
]
33+
},
34+
{
35+
"name" : "org.neo4j.driver.internal.shaded.io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueConsumerIndexField",
36+
"fields": [
37+
{"name": "consumerIndex", "allowUnsafeAccess": true}
38+
]
39+
},
40+
{
41+
"name" : "org.neo4j.driver.internal.shaded.io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueProducerFields",
42+
"fields": [
43+
{"name": "producerIndex", "allowUnsafeAccess": true}
44+
]
45+
},
46+
{
47+
"name" : "org.neo4j.driver.internal.shaded.io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueColdProducerFields",
48+
"fields": [
49+
{"name": "producerLimit", "allowUnsafeAccess": true}
50+
]
51+
},
52+
{
53+
"name" : "org.neo4j.driver.internal.shaded.io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueConsumerFields",
54+
"fields": [
55+
{"name": "consumerIndex", "allowUnsafeAccess": true}
56+
]
2157
}
2258
]

0 commit comments

Comments
 (0)