From f1495e19459eb4e961b1c078e7692680f88a0803 Mon Sep 17 00:00:00 2001 From: Paulo Lopes Date: Mon, 29 Apr 2019 08:39:42 +0200 Subject: [PATCH] Add SVM metadata and minimal substitutions to build graalvm native image applications. (#8963) Motivation: GraalVM native images are a new way to deliver java applications. Netty is one of the most popular libraries however there are a few limitations that make it impossible to use with native images out of the box. Adding a few metadata (in specific modules will allow the compilation to success and produce working binaries) Modification: Added properties files in `META-INF` and substitutions classes (under `internal.svm`) will solve the compilation issues. The substitutions classes are not visible and do not have a public constructor so they are not visible to end users. Result: Fixes #8959 This fix is very conservative as it applies the minimum config required to build: * pure netty servers * vert.x applications * grpc applications The build is having trouble due to checkstyle which does not seem to be able to find the copyright notice on property files. --- .../codec-http/native-image.properties | 15 +++ .../codec-http2/native-image.properties | 16 +++ common/pom.xml | 7 + .../svm/CleanerJava6Substitution.java | 33 +++++ .../svm/PlatformDependent0Substitution.java | 33 +++++ .../svm/PlatformDependentSubstitution.java | 39 ++++++ .../svm/UnsafeRefArrayAccessSubstitution.java | 32 +++++ .../netty/util/internal/svm/package-info.java | 21 +++ pom.xml | 17 +++ testsuite-native-image/pom.xml | 122 ++++++++++++++++++ .../netty/testsuite/svm/HttpNativeServer.java | 67 ++++++++++ .../svm/HttpNativeServerHandler.java | 67 ++++++++++ .../svm/HttpNativeServerInitializer.java | 34 +++++ .../io/netty/testsuite/svm/package-info.java | 20 +++ .../transport/native-image.properties | 15 +++ .../io.netty/transport/reflection-config.json | 8 ++ 16 files changed, 546 insertions(+) create mode 100644 codec-http/src/main/resources/META-INF/native-image/io.netty/codec-http/native-image.properties create mode 100644 codec-http2/src/main/resources/META-INF/native-image/io.netty/codec-http2/native-image.properties create mode 100644 common/src/main/java/io/netty/util/internal/svm/CleanerJava6Substitution.java create mode 100644 common/src/main/java/io/netty/util/internal/svm/PlatformDependent0Substitution.java create mode 100644 common/src/main/java/io/netty/util/internal/svm/PlatformDependentSubstitution.java create mode 100644 common/src/main/java/io/netty/util/internal/svm/UnsafeRefArrayAccessSubstitution.java create mode 100644 common/src/main/java/io/netty/util/internal/svm/package-info.java create mode 100644 testsuite-native-image/pom.xml create mode 100644 testsuite-native-image/src/main/java/io/netty/testsuite/svm/HttpNativeServer.java create mode 100644 testsuite-native-image/src/main/java/io/netty/testsuite/svm/HttpNativeServerHandler.java create mode 100644 testsuite-native-image/src/main/java/io/netty/testsuite/svm/HttpNativeServerInitializer.java create mode 100644 testsuite-native-image/src/main/java/io/netty/testsuite/svm/package-info.java create mode 100644 transport/src/main/resources/META-INF/native-image/io.netty/transport/native-image.properties create mode 100644 transport/src/main/resources/META-INF/native-image/io.netty/transport/reflection-config.json diff --git a/codec-http/src/main/resources/META-INF/native-image/io.netty/codec-http/native-image.properties b/codec-http/src/main/resources/META-INF/native-image/io.netty/codec-http/native-image.properties new file mode 100644 index 0000000000..96e9624e79 --- /dev/null +++ b/codec-http/src/main/resources/META-INF/native-image/io.netty/codec-http/native-image.properties @@ -0,0 +1,15 @@ +# Copyright 2019 The Netty Project +# +# The Netty Project licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +Args = --delay-class-initialization-to-runtime=io.netty.handler.codec.http.HttpObjectEncoder,io.netty.handler.codec.http.websocketx.WebSocket00FrameEncoder diff --git a/codec-http2/src/main/resources/META-INF/native-image/io.netty/codec-http2/native-image.properties b/codec-http2/src/main/resources/META-INF/native-image/io.netty/codec-http2/native-image.properties new file mode 100644 index 0000000000..9336d016eb --- /dev/null +++ b/codec-http2/src/main/resources/META-INF/native-image/io.netty/codec-http2/native-image.properties @@ -0,0 +1,16 @@ +# Copyright 2019 The Netty Project +# +# The Netty Project licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +Args = --rerun-class-initialization-at-runtime=io.netty.handler.codec.http2.Http2CodecUtil \ + --delay-class-initialization-to-runtime=io.netty.handler.codec.http2.DefaultHttp2FrameWriter diff --git a/common/pom.xml b/common/pom.xml index ef86991e03..d2f057dab6 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -38,6 +38,13 @@ + + com.oracle.substratevm + svm + ${graalvm.version} + + provided + org.jctools jctools-core diff --git a/common/src/main/java/io/netty/util/internal/svm/CleanerJava6Substitution.java b/common/src/main/java/io/netty/util/internal/svm/CleanerJava6Substitution.java new file mode 100644 index 0000000000..cd78c670b4 --- /dev/null +++ b/common/src/main/java/io/netty/util/internal/svm/CleanerJava6Substitution.java @@ -0,0 +1,33 @@ +/* + * Copyright 2019 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.netty.util.internal.svm; + +import com.oracle.svm.core.annotate.Alias; +import com.oracle.svm.core.annotate.RecomputeFieldValue; +import com.oracle.svm.core.annotate.TargetClass; + +@TargetClass(className = "io.netty.util.internal.CleanerJava6") +final class CleanerJava6Substitution { + private CleanerJava6Substitution() { + } + + @Alias + @RecomputeFieldValue( + kind = RecomputeFieldValue.Kind.FieldOffset, + declClassName = "java.nio.DirectByteBuffer", + name = "cleaner") + private static long CLEANER_FIELD_OFFSET; +} diff --git a/common/src/main/java/io/netty/util/internal/svm/PlatformDependent0Substitution.java b/common/src/main/java/io/netty/util/internal/svm/PlatformDependent0Substitution.java new file mode 100644 index 0000000000..01b9db292d --- /dev/null +++ b/common/src/main/java/io/netty/util/internal/svm/PlatformDependent0Substitution.java @@ -0,0 +1,33 @@ +/* + * Copyright 2019 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.netty.util.internal.svm; + +import com.oracle.svm.core.annotate.Alias; +import com.oracle.svm.core.annotate.RecomputeFieldValue; +import com.oracle.svm.core.annotate.TargetClass; + +@TargetClass(className = "io.netty.util.internal.PlatformDependent0") +final class PlatformDependent0Substitution { + private PlatformDependent0Substitution() { + } + + @Alias + @RecomputeFieldValue( + kind = RecomputeFieldValue.Kind.FieldOffset, + declClassName = "java.nio.Buffer", + name = "address") + private static long ADDRESS_FIELD_OFFSET; +} diff --git a/common/src/main/java/io/netty/util/internal/svm/PlatformDependentSubstitution.java b/common/src/main/java/io/netty/util/internal/svm/PlatformDependentSubstitution.java new file mode 100644 index 0000000000..1afe0a0aff --- /dev/null +++ b/common/src/main/java/io/netty/util/internal/svm/PlatformDependentSubstitution.java @@ -0,0 +1,39 @@ +/* + * Copyright 2019 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.netty.util.internal.svm; + +import com.oracle.svm.core.annotate.Alias; +import com.oracle.svm.core.annotate.RecomputeFieldValue; +import com.oracle.svm.core.annotate.TargetClass; + +@TargetClass(className = "io.netty.util.internal.PlatformDependent") +final class PlatformDependentSubstitution { + private PlatformDependentSubstitution() { + } + + /** + * The class PlatformDependent caches the byte array base offset by reading the + * field from PlatformDependent0. The automatic recomputation of Substrate VM + * correctly recomputes the field in PlatformDependent0, but since the caching + * in PlatformDependent happens during image building, the non-recomputed value + * is cached. + */ + @Alias + @RecomputeFieldValue( + kind = RecomputeFieldValue.Kind.ArrayBaseOffset, + declClass = byte[].class) + private static long BYTE_ARRAY_BASE_OFFSET; +} diff --git a/common/src/main/java/io/netty/util/internal/svm/UnsafeRefArrayAccessSubstitution.java b/common/src/main/java/io/netty/util/internal/svm/UnsafeRefArrayAccessSubstitution.java new file mode 100644 index 0000000000..732fe2864d --- /dev/null +++ b/common/src/main/java/io/netty/util/internal/svm/UnsafeRefArrayAccessSubstitution.java @@ -0,0 +1,32 @@ +/* + * Copyright 2019 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.netty.util.internal.svm; + +import com.oracle.svm.core.annotate.Alias; +import com.oracle.svm.core.annotate.RecomputeFieldValue; +import com.oracle.svm.core.annotate.TargetClass; + +@TargetClass(className = "io.netty.util.internal.shaded.org.jctools.util.UnsafeRefArrayAccess") +final class UnsafeRefArrayAccessSubstitution { + private UnsafeRefArrayAccessSubstitution() { + } + + @Alias + @RecomputeFieldValue( + kind = RecomputeFieldValue.Kind.ArrayIndexShift, + declClass = Object[].class) + public static int REF_ELEMENT_SHIFT; +} diff --git a/common/src/main/java/io/netty/util/internal/svm/package-info.java b/common/src/main/java/io/netty/util/internal/svm/package-info.java new file mode 100644 index 0000000000..e9b82ec031 --- /dev/null +++ b/common/src/main/java/io/netty/util/internal/svm/package-info.java @@ -0,0 +1,21 @@ +/* + * Copyright 2019 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +/** + * SVM substitutions for classes that will cause trouble while compiling + * into native image. + */ +package io.netty.util.internal.svm; diff --git a/pom.xml b/pom.xml index b92717f35f..94ad63fd3e 100644 --- a/pom.xml +++ b/pom.xml @@ -68,6 +68,19 @@ + + + graal + + + + ${java.home}/bin/native-image + + + + false + + java13 @@ -299,6 +312,9 @@ false false false + 1.0.0-rc15 + + true @@ -337,6 +353,7 @@ testsuite-http2 testsuite-osgi testsuite-shading + testsuite-native-image microbench bom diff --git a/testsuite-native-image/pom.xml b/testsuite-native-image/pom.xml new file mode 100644 index 0000000000..439f3b0209 --- /dev/null +++ b/testsuite-native-image/pom.xml @@ -0,0 +1,122 @@ + + + + + 4.0.0 + + io.netty + netty-parent + 4.1.36.Final-SNAPSHOT + + + netty-testsuite-native-image + jar + + Netty/Testsuite/NativeImage + + + true + + + + + ${project.groupId} + netty-common + ${project.version} + + + ${project.groupId} + netty-buffer + ${project.version} + + + ${project.groupId} + netty-transport + ${project.version} + + + ${project.groupId} + netty-handler + ${project.version} + + + ${project.groupId} + netty-codec-http + ${project.version} + + + + + + + skipTests + + + skipTests + + + + true + + + + + + + + com.oracle.substratevm + native-image-maven-plugin + ${graalvm.version} + + + + native-image + + package + + + + ${skipNativeImageTestsuite} + ${project.artifactId} + io.netty.testsuite.svm.HttpNativeServer + --report-unsupported-elements-at-runtime --allow-incomplete-classpath + + + + org.codehaus.mojo + exec-maven-plugin + 1.6.0 + + + + + verify-native-image + verify + + exec + + + + + ${skipNativeImageTestsuite} + ${project.build.directory}/${project.artifactId} + + + + + diff --git a/testsuite-native-image/src/main/java/io/netty/testsuite/svm/HttpNativeServer.java b/testsuite-native-image/src/main/java/io/netty/testsuite/svm/HttpNativeServer.java new file mode 100644 index 0000000000..033d80939f --- /dev/null +++ b/testsuite-native-image/src/main/java/io/netty/testsuite/svm/HttpNativeServer.java @@ -0,0 +1,67 @@ +/* + * Copyright 2019 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.netty.testsuite.svm; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; +import io.netty.handler.ssl.SslContext; +import io.netty.handler.ssl.SslContextBuilder; +import io.netty.handler.ssl.util.SelfSignedCertificate; + +/** + * An HTTP server that sends back the content of the received HTTP request + * in a pretty plaintext form. + */ +public final class HttpNativeServer { + + /** + * Main entry point (not instantiable) + */ + private HttpNativeServer() { + } + + public static void main(String[] args) throws Exception { + // Configure the server. + EventLoopGroup bossGroup = new NioEventLoopGroup(1); + EventLoopGroup workerGroup = new NioEventLoopGroup(); + // Control status. + boolean serverStartSucess = false; + try { + ServerBootstrap b = new ServerBootstrap(); + b.option(ChannelOption.SO_BACKLOG, 1024); + b.group(bossGroup, workerGroup) + .channel(NioServerSocketChannel.class) + .handler(new LoggingHandler(LogLevel.INFO)) + .childHandler(new HttpNativeServerInitializer()); + + Channel channel = b.bind(0).sync().channel(); + System.err.println("Server started, will shutdown now."); + channel.close().sync(); + serverStartSucess = true; + } finally { + bossGroup.shutdownGracefully(); + workerGroup.shutdownGracefully(); + } + // return the right system exit code to signal success + System.exit(serverStartSucess ? 0 : 1); + } +} diff --git a/testsuite-native-image/src/main/java/io/netty/testsuite/svm/HttpNativeServerHandler.java b/testsuite-native-image/src/main/java/io/netty/testsuite/svm/HttpNativeServerHandler.java new file mode 100644 index 0000000000..33531dca54 --- /dev/null +++ b/testsuite-native-image/src/main/java/io/netty/testsuite/svm/HttpNativeServerHandler.java @@ -0,0 +1,67 @@ +/* + * Copyright 2013 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.netty.testsuite.svm; + +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelFutureListener; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.http.DefaultFullHttpResponse; +import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpObject; +import io.netty.handler.codec.http.HttpUtil; +import io.netty.handler.codec.http.HttpRequest; +import io.netty.util.AsciiString; + +import static io.netty.handler.codec.http.HttpHeaderNames.*; +import static io.netty.handler.codec.http.HttpResponseStatus.*; +import static io.netty.handler.codec.http.HttpVersion.*; + +public class HttpNativeServerHandler extends SimpleChannelInboundHandler { + private static final byte[] CONTENT = { 'H', 'e', 'l', 'l', 'o', ' ', 'N', 'a', 't', 'i', 'v', 'e' }; + + private static final AsciiString KEEP_ALIVE = AsciiString.cached("keep-alive"); + + @Override + public void channelReadComplete(ChannelHandlerContext ctx) { + ctx.flush(); + } + + @Override + public void channelRead0(ChannelHandlerContext ctx, HttpObject msg) { + if (msg instanceof HttpRequest) { + HttpRequest req = (HttpRequest) msg; + + boolean keepAlive = HttpUtil.isKeepAlive(req); + FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, OK, Unpooled.wrappedBuffer(CONTENT)); + response.headers().set(CONTENT_TYPE, "text/plain"); + response.headers().setInt(CONTENT_LENGTH, response.content().readableBytes()); + + if (!keepAlive) { + ctx.write(response).addListener(ChannelFutureListener.CLOSE); + } else { + response.headers().set(CONNECTION, KEEP_ALIVE); + ctx.write(response); + } + } + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { + cause.printStackTrace(); + ctx.close(); + } +} diff --git a/testsuite-native-image/src/main/java/io/netty/testsuite/svm/HttpNativeServerInitializer.java b/testsuite-native-image/src/main/java/io/netty/testsuite/svm/HttpNativeServerInitializer.java new file mode 100644 index 0000000000..c326c6a7ad --- /dev/null +++ b/testsuite-native-image/src/main/java/io/netty/testsuite/svm/HttpNativeServerInitializer.java @@ -0,0 +1,34 @@ +/* + * Copyright 2019 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.netty.testsuite.svm; + +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.codec.http.HttpServerCodec; +import io.netty.handler.codec.http.HttpServerExpectContinueHandler; +import io.netty.handler.ssl.SslContext; + +public class HttpNativeServerInitializer extends ChannelInitializer { + + @Override + public void initChannel(SocketChannel ch) { + ChannelPipeline p = ch.pipeline(); + p.addLast(new HttpServerCodec()); + p.addLast(new HttpServerExpectContinueHandler()); + p.addLast(new HttpNativeServerHandler()); + } +} diff --git a/testsuite-native-image/src/main/java/io/netty/testsuite/svm/package-info.java b/testsuite-native-image/src/main/java/io/netty/testsuite/svm/package-info.java new file mode 100644 index 0000000000..89c639a694 --- /dev/null +++ b/testsuite-native-image/src/main/java/io/netty/testsuite/svm/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2019 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +/** + * A hello world server that should be compiled to native. + */ +package io.netty.testsuite.svm; diff --git a/transport/src/main/resources/META-INF/native-image/io.netty/transport/native-image.properties b/transport/src/main/resources/META-INF/native-image/io.netty/transport/native-image.properties new file mode 100644 index 0000000000..dc3356124d --- /dev/null +++ b/transport/src/main/resources/META-INF/native-image/io.netty/transport/native-image.properties @@ -0,0 +1,15 @@ +# Copyright 2019 The Netty Project +# +# The Netty Project licenses this file to you under the Apache License, +# version 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +Args = -H:ReflectionConfigurationResources=${.}/reflection-config.json diff --git a/transport/src/main/resources/META-INF/native-image/io.netty/transport/reflection-config.json b/transport/src/main/resources/META-INF/native-image/io.netty/transport/reflection-config.json new file mode 100644 index 0000000000..929eb40be8 --- /dev/null +++ b/transport/src/main/resources/META-INF/native-image/io.netty/transport/reflection-config.json @@ -0,0 +1,8 @@ +[ + { + "name": "io.netty.channel.socket.nio.NioServerSocketChannel", + "methods": [ + { "name": "", "parameterTypes": [] } + ] + } +]