You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by pp...@apache.org on 2020/09/01 14:05:21 UTC

[camel-quarkus] branch camel-master updated: Fix #1664 KuduIT fails with Camel 3.5.0

This is an automated email from the ASF dual-hosted git repository.

ppalaga pushed a commit to branch camel-master
in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git


The following commit(s) were added to refs/heads/camel-master by this push:
     new c46d142  Fix #1664 KuduIT fails with Camel 3.5.0
c46d142 is described below

commit c46d14230b08283c002b7d5fd97a2daf8d83b341
Author: Peter Palaga <pp...@redhat.com>
AuthorDate: Tue Sep 1 13:42:15 2020 +0200

    Fix #1664 KuduIT fails with Camel 3.5.0
---
 .../kudu/deployment/JBossNettyLoggerFactory.java   | 197 +++++++++
 .../component/kudu/deployment/KuduProcessor.java   | 169 ++++++++
 extensions/kudu/runtime/pom.xml                    |   5 +
 .../component/kudu/graal/EmptyByteBufStub.java     |  53 +++
 .../component/kudu/graal/NettySubstitutions.java   | 453 +++++++++++++++++++++
 .../component/kudu/graal/ZLibSubstitutions.java    |  88 ++++
 6 files changed, 965 insertions(+)

diff --git a/extensions/kudu/deployment/src/main/java/org/apache/camel/quarkus/component/kudu/deployment/JBossNettyLoggerFactory.java b/extensions/kudu/deployment/src/main/java/org/apache/camel/quarkus/component/kudu/deployment/JBossNettyLoggerFactory.java
new file mode 100644
index 0000000..0e2520b
--- /dev/null
+++ b/extensions/kudu/deployment/src/main/java/org/apache/camel/quarkus/component/kudu/deployment/JBossNettyLoggerFactory.java
@@ -0,0 +1,197 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 org.apache.camel.quarkus.component.kudu.deployment;
+
+import org.apache.kudu.shaded.io.netty.util.internal.logging.AbstractInternalLogger;
+import org.apache.kudu.shaded.io.netty.util.internal.logging.InternalLogger;
+import org.apache.kudu.shaded.io.netty.util.internal.logging.InternalLoggerFactory;
+import org.jboss.logging.Logger;
+
+/**
+ * Adapted from
+ * https://github.com/quarkusio/quarkus/blob/master/extensions/netty/deployment/src/main/java/io/quarkus/netty/deployment/JBossNettyLoggerFactory.java
+ *
+ */
+public class JBossNettyLoggerFactory extends InternalLoggerFactory {
+
+    @Override
+    protected InternalLogger newInstance(String name) {
+        return new JBossNettyInternalLogger(name);
+    }
+
+    private static final class JBossNettyInternalLogger extends AbstractInternalLogger {
+
+        final Logger log;
+
+        JBossNettyInternalLogger(String name) {
+            super(name);
+            log = Logger.getLogger(name);
+        }
+
+        @Override
+        public boolean isTraceEnabled() {
+            return log.isTraceEnabled();
+        }
+
+        @Override
+        public void trace(String msg) {
+            log.trace(msg);
+        }
+
+        @Override
+        public void trace(String format, Object arg) {
+            log.tracef(format, arg);
+        }
+
+        @Override
+        public void trace(String format, Object argA, Object argB) {
+            log.tracef(format, argA, argB);
+        }
+
+        @Override
+        public void trace(String format, Object... arguments) {
+            log.tracef(format, arguments);
+        }
+
+        @Override
+        public void trace(String msg, Throwable t) {
+            log.trace(msg, t);
+        }
+
+        @Override
+        public boolean isDebugEnabled() {
+            return log.isDebugEnabled();
+        }
+
+        @Override
+        public void debug(String msg) {
+            log.debug(msg);
+        }
+
+        @Override
+        public void debug(String format, Object arg) {
+            log.debugf(format, arg);
+        }
+
+        @Override
+        public void debug(String format, Object argA, Object argB) {
+            log.debugf(format, argA, argB);
+        }
+
+        @Override
+        public void debug(String format, Object... arguments) {
+            log.debugf(format, arguments);
+        }
+
+        @Override
+        public void debug(String msg, Throwable t) {
+            log.debug(msg, t);
+        }
+
+        @Override
+        public boolean isInfoEnabled() {
+            return log.isInfoEnabled();
+        }
+
+        @Override
+        public void info(String msg) {
+            log.info(msg);
+        }
+
+        @Override
+        public void info(String format, Object arg) {
+            log.infof(format, arg);
+        }
+
+        @Override
+        public void info(String format, Object argA, Object argB) {
+            log.infof(format, argA, argB);
+        }
+
+        @Override
+        public void info(String format, Object... arguments) {
+            log.infof(format, arguments);
+        }
+
+        @Override
+        public void info(String msg, Throwable t) {
+            log.info(msg, t);
+        }
+
+        @Override
+        public boolean isWarnEnabled() {
+            return log.isEnabled(Logger.Level.WARN);
+        }
+
+        @Override
+        public void warn(String msg) {
+            log.warn(msg);
+        }
+
+        @Override
+        public void warn(String format, Object arg) {
+            log.warnf(format, arg);
+        }
+
+        @Override
+        public void warn(String format, Object... arguments) {
+            log.warnf(format, arguments);
+        }
+
+        @Override
+        public void warn(String format, Object argA, Object argB) {
+            log.warnf(format, argA, argB);
+        }
+
+        @Override
+        public void warn(String msg, Throwable t) {
+            log.warn(msg, t);
+        }
+
+        @Override
+        public boolean isErrorEnabled() {
+            return log.isEnabled(Logger.Level.ERROR);
+        }
+
+        @Override
+        public void error(String msg) {
+            log.error(msg);
+        }
+
+        @Override
+        public void error(String format, Object arg) {
+            log.errorf(format, arg);
+        }
+
+        @Override
+        public void error(String format, Object argA, Object argB) {
+            log.errorf(format, argA, argB);
+        }
+
+        @Override
+        public void error(String format, Object... arguments) {
+            log.errorf(format, arguments);
+        }
+
+        @Override
+        public void error(String msg, Throwable t) {
+            log.error(msg, t);
+        }
+
+    }
+
+}
diff --git a/extensions/kudu/deployment/src/main/java/org/apache/camel/quarkus/component/kudu/deployment/KuduProcessor.java b/extensions/kudu/deployment/src/main/java/org/apache/camel/quarkus/component/kudu/deployment/KuduProcessor.java
index d130641..56dee82 100644
--- a/extensions/kudu/deployment/src/main/java/org/apache/camel/quarkus/component/kudu/deployment/KuduProcessor.java
+++ b/extensions/kudu/deployment/src/main/java/org/apache/camel/quarkus/component/kudu/deployment/KuduProcessor.java
@@ -16,11 +16,27 @@
  */
 package org.apache.camel.quarkus.component.kudu.deployment;
 
+import java.util.Arrays;
+import java.util.List;
+
+import io.quarkus.deployment.annotations.BuildProducer;
 import io.quarkus.deployment.annotations.BuildStep;
 import io.quarkus.deployment.builditem.ExtensionSslNativeSupportBuildItem;
 import io.quarkus.deployment.builditem.FeatureBuildItem;
+import io.quarkus.deployment.builditem.nativeimage.NativeImageConfigBuildItem;
+import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
+import io.quarkus.deployment.builditem.nativeimage.RuntimeInitializedClassBuildItem;
+import io.quarkus.deployment.builditem.nativeimage.RuntimeReinitializedClassBuildItem;
+import io.quarkus.deployment.builditem.nativeimage.UnsafeAccessedFieldBuildItem;
+import org.apache.camel.quarkus.component.kudu.graal.EmptyByteBufStub;
+import org.apache.kudu.shaded.io.netty.util.internal.logging.InternalLoggerFactory;
+import org.jboss.logging.Logger;
 
 class KuduProcessor {
+    private static final Logger LOGGER = Logger.getLogger(KuduProcessor.class);
+    static {
+        InternalLoggerFactory.setDefaultFactory(new JBossNettyLoggerFactory());
+    }
 
     private static final String FEATURE = "camel-kudu";
 
@@ -34,4 +50,157 @@ class KuduProcessor {
         return new ExtensionSslNativeSupportBuildItem(FEATURE);
     }
 
+    @BuildStep
+    void reflection(BuildProducer<ReflectiveClassBuildItem> reflectiveClass) {
+        reflectiveClass.produce(new ReflectiveClassBuildItem(true, false,
+                "org.apache.kudu.tserver.Tserver$ResourceMetricsPB",
+                "org.apache.kudu.tserver.Tserver$ResourceMetricsPB$Builder"));
+    }
+
+    /*
+     * Adapted from https://github.com/quarkusio/quarkus/blob/master/extensions/netty/deployment/src/main/java/io/quarkus/netty/deployment/NettyProcessor.java
+     */
+    @BuildStep
+    void netty(
+            BuildProducer<NativeImageConfigBuildItem> nativeImageConfig,
+            BuildProducer<ReflectiveClassBuildItem> reflectiveClass) {
+
+        reflectiveClass.produce(new ReflectiveClassBuildItem(true, false,
+                "org.apache.kudu.tserver.Tserver$ResourceMetricsPB",
+                "org.apache.kudu.tserver.Tserver$ResourceMetricsPB$Builder"));
+
+        reflectiveClass.produce(new ReflectiveClassBuildItem(false, false,
+                "org.apache.kudu.shaded.io.netty.channel.socket.nio.NioSocketChannel"));
+        reflectiveClass
+                .produce(new ReflectiveClassBuildItem(false, false,
+                        "org.apache.kudu.shaded.io.netty.channel.socket.nio.NioServerSocketChannel"));
+        reflectiveClass.produce(new ReflectiveClassBuildItem(false, false, "java.util.LinkedHashMap"));
+        reflectiveClass.produce(new ReflectiveClassBuildItem(true, true, "sun.nio.ch.SelectorImpl"));
+
+        NativeImageConfigBuildItem.Builder builder = NativeImageConfigBuildItem.builder()
+                //.addNativeImageSystemProperty("io.netty.noUnsafe", "true")
+                // Use small chunks to avoid a lot of wasted space. Default is 16mb * arenas (derived from core count)
+                // Since buffers are cached to threads, the malloc overhead is temporary anyway
+                .addNativeImageSystemProperty("io.netty.allocator.maxOrder", "1")
+                .addRuntimeInitializedClass("org.apache.kudu.shaded.io.netty.handler.ssl.JdkNpnApplicationProtocolNegotiator")
+                .addRuntimeInitializedClass("org.apache.kudu.shaded.io.netty.handler.ssl.ConscryptAlpnSslEngine")
+                .addRuntimeInitializedClass("org.apache.kudu.shaded.io.netty.handler.ssl.ReferenceCountedOpenSslEngine")
+                .addRuntimeInitializedClass("org.apache.kudu.shaded.io.netty.handler.ssl.ReferenceCountedOpenSslContext")
+                .addRuntimeInitializedClass("org.apache.kudu.shaded.io.netty.handler.ssl.ReferenceCountedOpenSslClientContext")
+                .addRuntimeInitializedClass("org.apache.kudu.shaded.io.netty.handler.ssl.util.ThreadLocalInsecureRandom")
+                .addRuntimeInitializedClass("org.apache.kudu.shaded.io.netty.buffer.ByteBufUtil$HexUtil")
+                .addRuntimeInitializedClass("org.apache.kudu.shaded.io.netty.buffer.PooledByteBufAllocator")
+                .addRuntimeInitializedClass("org.apache.kudu.shaded.io.netty.buffer.ByteBufAllocator")
+                .addRuntimeInitializedClass("org.apache.kudu.shaded.io.netty.buffer.ByteBufUtil")
+                .addNativeImageSystemProperty("io.netty.leakDetection.level", "DISABLED");
+
+        try {
+            Class.forName("org.apache.kudu.shaded.io.netty.handler.codec.http.HttpObjectEncoder");
+            builder
+                    .addRuntimeInitializedClass("org.apache.kudu.shaded.io.netty.handler.codec.http.HttpObjectEncoder")
+                    .addRuntimeInitializedClass(
+                            "org.apache.kudu.shaded.io.netty.handler.codec.http.websocketx.extensions.compression.DeflateDecoder")
+                    .addRuntimeInitializedClass(
+                            "org.apache.kudu.shaded.io.netty.handler.codec.http.websocketx.WebSocket00FrameEncoder");
+        } catch (ClassNotFoundException e) {
+            //ignore
+            LOGGER.debug("Not registering Netty HTTP classes as they were not found");
+        }
+
+        try {
+            Class.forName("org.apache.kudu.shaded.io.netty.handler.codec.http2.Http2CodecUtil");
+            builder
+                    .addRuntimeInitializedClass("org.apache.kudu.shaded.io.netty.handler.codec.http2.Http2CodecUtil")
+                    .addRuntimeInitializedClass("org.apache.kudu.shaded.io.netty.handler.codec.http2.Http2ClientUpgradeCodec")
+                    .addRuntimeInitializedClass("org.apache.kudu.shaded.io.netty.handler.codec.http2.DefaultHttp2FrameWriter")
+                    .addRuntimeInitializedClass("org.apache.kudu.shaded.io.netty.handler.codec.http2.Http2ConnectionHandler");
+        } catch (ClassNotFoundException e) {
+            //ignore
+            LOGGER.debug("Not registering Netty HTTP2 classes as they were not found");
+        }
+
+        try {
+            Class.forName("org.apache.kudu.shaded.io.netty.channel.unix.UnixChannel");
+            builder.addRuntimeInitializedClass("org.apache.kudu.shaded.io.netty.channel.unix.Errors")
+                    .addRuntimeInitializedClass("org.apache.kudu.shaded.io.netty.channel.unix.FileDescriptor")
+                    .addRuntimeInitializedClass("org.apache.kudu.shaded.io.netty.channel.unix.IovArray")
+                    .addRuntimeInitializedClass("org.apache.kudu.shaded.io.netty.channel.unix.Limits");
+        } catch (ClassNotFoundException e) {
+            //ignore
+            LOGGER.debug("Not registering Netty native unix classes as they were not found");
+        }
+
+        try {
+            Class.forName("org.apache.kudu.shaded.io.netty.channel.epoll.EpollMode");
+            builder.addRuntimeInitializedClass("org.apache.kudu.shaded.io.netty.channel.epoll.Epoll")
+                    .addRuntimeInitializedClass("org.apache.kudu.shaded.io.netty.channel.epoll.EpollEventArray")
+                    .addRuntimeInitializedClass("org.apache.kudu.shaded.io.netty.channel.epoll.EpollEventLoop")
+                    .addRuntimeInitializedClass("org.apache.kudu.shaded.io.netty.channel.epoll.Native");
+        } catch (ClassNotFoundException e) {
+            //ignore
+            LOGGER.debug("Not registering Netty native epoll classes as they were not found");
+        }
+
+        try {
+            Class.forName("org.apache.kudu.shaded.io.netty.channel.kqueue.AcceptFilter");
+            builder.addRuntimeInitializedClass("org.apache.kudu.shaded.io.netty.channel.kqueue.KQueue")
+                    .addRuntimeInitializedClass("org.apache.kudu.shaded.io.netty.channel.kqueue.KQueueEventArray")
+                    .addRuntimeInitializedClass("org.apache.kudu.shaded.io.netty.channel.kqueue.KQueueEventLoop")
+                    .addRuntimeInitializedClass("org.apache.kudu.shaded.io.netty.channel.kqueue.Native");
+        } catch (ClassNotFoundException e) {
+            //ignore
+            LOGGER.debug("Not registering Netty native kqueue classes as they were not found");
+        }
+
+        nativeImageConfig.produce(builder.build());
+    }
+
+    /*
+     * Adapted from https://github.com/quarkusio/quarkus/blob/master/extensions/netty/deployment/src/main/java/io/quarkus/netty/deployment/NettyProcessor.java
+     */
+    @BuildStep
+    public RuntimeReinitializedClassBuildItem nettyReinitScheduledFutureTask() {
+        return new RuntimeReinitializedClassBuildItem(
+                "org.apache.camel.quarkus.component.kudu.graal.Holder_io_netty_util_concurrent_ScheduledFutureTask");
+    }
+
+    /*
+     * Adapted from https://github.com/quarkusio/quarkus/blob/master/extensions/netty/deployment/src/main/java/io/quarkus/netty/deployment/NettyProcessor.java
+     */
+    @BuildStep
+    public List<UnsafeAccessedFieldBuildItem> nettyUnsafeAccessedFields() {
+        return Arrays.asList(
+                new UnsafeAccessedFieldBuildItem("sun.nio.ch.SelectorImpl", "selectedKeys"),
+                new UnsafeAccessedFieldBuildItem("sun.nio.ch.SelectorImpl", "publicSelectedKeys"),
+
+                new UnsafeAccessedFieldBuildItem(
+                        "org.apache.kudu.shaded.io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueProducerIndexField",
+                        "producerIndex"),
+                new UnsafeAccessedFieldBuildItem(
+                        "org.apache.kudu.shaded.io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueProducerLimitField",
+                        "producerLimit"),
+                new UnsafeAccessedFieldBuildItem(
+                        "org.apache.kudu.shaded.io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueConsumerIndexField",
+                        "consumerIndex"),
+
+                new UnsafeAccessedFieldBuildItem(
+                        "org.apache.kudu.shaded.io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueProducerFields",
+                        "producerIndex"),
+                new UnsafeAccessedFieldBuildItem(
+                        "org.apache.kudu.shaded.io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueColdProducerFields",
+                        "producerLimit"),
+                new UnsafeAccessedFieldBuildItem(
+                        "org.apache.kudu.shaded.io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueConsumerFields",
+                        "consumerIndex"));
+    }
+
+    /*
+     * Adapted from https://github.com/quarkusio/quarkus/blob/master/extensions/netty/deployment/src/main/java/io/quarkus/netty/deployment/NettyProcessor.java
+     */
+    @BuildStep
+    RuntimeInitializedClassBuildItem nettyRuntimeInitBcryptUtil() {
+        // this holds a direct allocated byte buffer that needs to be initialised at run time
+        return new RuntimeInitializedClassBuildItem(EmptyByteBufStub.class.getName());
+    }
+
 }
diff --git a/extensions/kudu/runtime/pom.xml b/extensions/kudu/runtime/pom.xml
index ee37afd..11403aa 100644
--- a/extensions/kudu/runtime/pom.xml
+++ b/extensions/kudu/runtime/pom.xml
@@ -54,6 +54,11 @@
             <groupId>org.apache.camel</groupId>
             <artifactId>camel-kudu</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.graalvm.nativeimage</groupId>
+            <artifactId>svm</artifactId>
+            <scope>provided</scope>
+        </dependency>
     </dependencies>
 
     <build>
diff --git a/extensions/kudu/runtime/src/main/java/org/apache/camel/quarkus/component/kudu/graal/EmptyByteBufStub.java b/extensions/kudu/runtime/src/main/java/org/apache/camel/quarkus/component/kudu/graal/EmptyByteBufStub.java
new file mode 100644
index 0000000..0bd25f9
--- /dev/null
+++ b/extensions/kudu/runtime/src/main/java/org/apache/camel/quarkus/component/kudu/graal/EmptyByteBufStub.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 org.apache.camel.quarkus.component.kudu.graal;
+
+import java.nio.ByteBuffer;
+
+import org.apache.kudu.shaded.io.netty.util.internal.PlatformDependent;
+
+/**
+ * Adapted from
+ * https://github.com/quarkusio/quarkus/blob/master/extensions/netty/runtime/src/main/java/io/quarkus/netty/runtime/EmptyByteBufStub.java
+ */
+public final class EmptyByteBufStub {
+    private static final ByteBuffer EMPTY_BYTE_BUFFER = ByteBuffer.allocateDirect(0);
+    private static final long EMPTY_BYTE_BUFFER_ADDRESS;
+
+    static {
+        long emptyByteBufferAddress = 0;
+        try {
+            if (PlatformDependent.hasUnsafe()) {
+                emptyByteBufferAddress = PlatformDependent.directBufferAddress(EMPTY_BYTE_BUFFER);
+            }
+        } catch (Throwable t) {
+            // Ignore
+        }
+        EMPTY_BYTE_BUFFER_ADDRESS = emptyByteBufferAddress;
+    }
+
+    public static ByteBuffer emptyByteBuffer() {
+        return EMPTY_BYTE_BUFFER;
+    }
+
+    public static long emptyByteBufferAddress() {
+        return EMPTY_BYTE_BUFFER_ADDRESS;
+    }
+
+    private EmptyByteBufStub() {
+    }
+}
diff --git a/extensions/kudu/runtime/src/main/java/org/apache/camel/quarkus/component/kudu/graal/NettySubstitutions.java b/extensions/kudu/runtime/src/main/java/org/apache/camel/quarkus/component/kudu/graal/NettySubstitutions.java
new file mode 100644
index 0000000..6a498c6
--- /dev/null
+++ b/extensions/kudu/runtime/src/main/java/org/apache/camel/quarkus/component/kudu/graal/NettySubstitutions.java
@@ -0,0 +1,453 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 org.apache.camel.quarkus.component.kudu.graal;
+
+import java.nio.ByteBuffer;
+import java.security.PrivateKey;
+import java.security.Provider;
+import java.security.cert.X509Certificate;
+import java.util.Queue;
+import java.util.concurrent.LinkedBlockingDeque;
+
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLEngine;
+import javax.net.ssl.SSLException;
+import javax.net.ssl.TrustManagerFactory;
+
+import com.oracle.svm.core.annotate.Alias;
+import com.oracle.svm.core.annotate.RecomputeFieldValue;
+import com.oracle.svm.core.annotate.Substitute;
+import com.oracle.svm.core.annotate.TargetClass;
+import com.oracle.svm.core.jdk.JDK8OrEarlier;
+import org.apache.kudu.shaded.io.netty.bootstrap.AbstractBootstrapConfig;
+import org.apache.kudu.shaded.io.netty.bootstrap.ChannelFactory;
+import org.apache.kudu.shaded.io.netty.buffer.ByteBufAllocator;
+import org.apache.kudu.shaded.io.netty.channel.Channel;
+import org.apache.kudu.shaded.io.netty.channel.ChannelFuture;
+import org.apache.kudu.shaded.io.netty.channel.DefaultChannelPromise;
+import org.apache.kudu.shaded.io.netty.handler.ssl.ApplicationProtocolConfig;
+import org.apache.kudu.shaded.io.netty.handler.ssl.ApplicationProtocolConfig.SelectorFailureBehavior;
+import org.apache.kudu.shaded.io.netty.handler.ssl.CipherSuiteFilter;
+import org.apache.kudu.shaded.io.netty.handler.ssl.ClientAuth;
+import org.apache.kudu.shaded.io.netty.handler.ssl.JdkAlpnApplicationProtocolNegotiator;
+import org.apache.kudu.shaded.io.netty.handler.ssl.JdkApplicationProtocolNegotiator;
+import org.apache.kudu.shaded.io.netty.handler.ssl.SslContext;
+import org.apache.kudu.shaded.io.netty.handler.ssl.SslProvider;
+import org.apache.kudu.shaded.io.netty.util.concurrent.GlobalEventExecutor;
+import org.apache.kudu.shaded.io.netty.util.internal.logging.InternalLoggerFactory;
+import org.apache.kudu.shaded.io.netty.util.internal.logging.JdkLoggerFactory;
+
+/**
+ * This substitution avoid having loggers added to the build.
+ * Adapted from
+ * https://github.com/quarkusio/quarkus/blob/master/extensions/netty/runtime/src/main/java/io/quarkus/netty/runtime/graal/NettySubstitutions.java
+ */
+@TargetClass(className = "org.apache.kudu.shaded.io.netty.util.internal.logging.InternalLoggerFactory")
+final class Target_io_netty_util_internal_logging_InternalLoggerFactory {
+
+    @Substitute
+    private static InternalLoggerFactory newDefaultFactory(String name) {
+        return JdkLoggerFactory.INSTANCE;
+    }
+}
+
+// SSL
+// This whole section is mostly about removing static analysis references to openssl/tcnative
+
+@TargetClass(className = "org.apache.kudu.shaded.io.netty.handler.ssl.JdkSslServerContext")
+final class Target_io_netty_handler_ssl_JdkSslServerContext {
+
+    @Alias
+    Target_io_netty_handler_ssl_JdkSslServerContext(Provider provider,
+            X509Certificate[] trustCertCollection, TrustManagerFactory trustManagerFactory,
+            X509Certificate[] keyCertChain, PrivateKey key, String keyPassword,
+            KeyManagerFactory keyManagerFactory, Iterable<String> ciphers, CipherSuiteFilter cipherFilter,
+            ApplicationProtocolConfig apn, long sessionCacheSize, long sessionTimeout,
+            ClientAuth clientAuth, String[] protocols, boolean startTls,
+            String keyStore)
+            throws SSLException {
+    }
+}
+
+@TargetClass(className = "org.apache.kudu.shaded.io.netty.handler.ssl.JdkSslClientContext")
+final class Target_io_netty_handler_ssl_JdkSslClientContext {
+
+    @Alias
+    Target_io_netty_handler_ssl_JdkSslClientContext(Provider sslContextProvider, X509Certificate[] trustCertCollection,
+            TrustManagerFactory trustManagerFactory, X509Certificate[] keyCertChain, PrivateKey key,
+            String keyPassword, KeyManagerFactory keyManagerFactory, Iterable<String> ciphers,
+            CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn, String[] protocols,
+            long sessionCacheSize, long sessionTimeout, String keyStoreType)
+            throws SSLException {
+
+    }
+}
+
+@TargetClass(className = "org.apache.kudu.shaded.io.netty.handler.ssl.SslHandler$SslEngineType")
+final class Target_io_netty_handler_ssl_SslHandler$SslEngineType {
+
+    @Alias
+    public static Target_io_netty_handler_ssl_SslHandler$SslEngineType JDK;
+
+    @Substitute
+    static Target_io_netty_handler_ssl_SslHandler$SslEngineType forEngine(SSLEngine engine) {
+        return JDK;
+    }
+}
+//
+//@TargetClass(className = "org.apache.kudu.shaded.io.netty.handler.ssl.JdkAlpnApplicationProtocolNegotiator$AlpnWrapper", onlyWith = JDK11OrLater.class)
+//final class Target_io_netty_handler_ssl_JdkAlpnApplicationProtocolNegotiator_AlpnWrapper {
+//    @Substitute
+//    public SSLEngine wrapSslEngine(SSLEngine engine, ByteBufAllocator alloc,
+//            JdkApplicationProtocolNegotiator applicationNegotiator, boolean isServer) {
+//        return (SSLEngine) (Object) new Target_io_netty_handler_ssl_JdkAlpnSslEngine(engine, applicationNegotiator, isServer);
+//    }
+//
+//}
+
+@TargetClass(className = "org.apache.kudu.shaded.io.netty.handler.ssl.JdkAlpnApplicationProtocolNegotiator$AlpnWrapper", onlyWith = JDK8OrEarlier.class)
+final class Target_io_netty_handler_ssl_JdkAlpnApplicationProtocolNegotiator_AlpnWrapperJava8 {
+    @Substitute
+    public SSLEngine wrapSslEngine(SSLEngine engine, ByteBufAllocator alloc,
+            JdkApplicationProtocolNegotiator applicationNegotiator, boolean isServer) {
+        if (Target_io_netty_handler_ssl_JettyAlpnSslEngine.isAvailable()) {
+            return isServer
+                    ? (SSLEngine) (Object) Target_io_netty_handler_ssl_JettyAlpnSslEngine.newServerEngine(engine,
+                            applicationNegotiator)
+                    : (SSLEngine) (Object) Target_io_netty_handler_ssl_JettyAlpnSslEngine.newClientEngine(engine,
+                            applicationNegotiator);
+        }
+        throw new RuntimeException("Unable to wrap SSLEngine of type " + engine.getClass().getName());
+    }
+
+}
+
+@TargetClass(className = "org.apache.kudu.shaded.io.netty.handler.ssl.JettyAlpnSslEngine", onlyWith = JDK8OrEarlier.class)
+final class Target_io_netty_handler_ssl_JettyAlpnSslEngine {
+    @Substitute
+    static boolean isAvailable() {
+        return false;
+    }
+
+    @Substitute
+    static Target_io_netty_handler_ssl_JettyAlpnSslEngine newClientEngine(SSLEngine engine,
+            JdkApplicationProtocolNegotiator applicationNegotiator) {
+        return null;
+    }
+
+    @Substitute
+    static Target_io_netty_handler_ssl_JettyAlpnSslEngine newServerEngine(SSLEngine engine,
+            JdkApplicationProtocolNegotiator applicationNegotiator) {
+        return null;
+    }
+}
+//
+//@TargetClass(className = "org.apache.kudu.shaded.io.netty.handler.ssl.JdkAlpnSslEngine", onlyWith = JDK11OrLater.class)
+//final class Target_io_netty_handler_ssl_JdkAlpnSslEngine {
+//    @Alias
+//    Target_io_netty_handler_ssl_JdkAlpnSslEngine(final SSLEngine engine,
+//            final JdkApplicationProtocolNegotiator applicationNegotiator, final boolean isServer) {
+//
+//    }
+//}
+
+@TargetClass(className = "org.apache.kudu.shaded.io.netty.handler.ssl.SslContext")
+final class Target_io_netty_handler_ssl_SslContext {
+
+    @Substitute
+    static SslContext newServerContextInternal(SslProvider provider,
+            Provider sslContextProvider,
+            X509Certificate[] trustCertCollection, TrustManagerFactory trustManagerFactory,
+            X509Certificate[] keyCertChain, PrivateKey key, String keyPassword, KeyManagerFactory keyManagerFactory,
+            Iterable<String> ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn,
+            long sessionCacheSize, long sessionTimeout, ClientAuth clientAuth, String[] protocols, boolean startTls,
+            boolean enableOcsp, String keyStoreType)
+            throws SSLException {
+
+        if (enableOcsp) {
+            throw new IllegalArgumentException("OCSP is not supported with this SslProvider: " + provider);
+        }
+        return (SslContext) (Object) new Target_io_netty_handler_ssl_JdkSslServerContext(sslContextProvider,
+                trustCertCollection, trustManagerFactory, keyCertChain, key, keyPassword,
+                keyManagerFactory, ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout,
+                clientAuth, protocols, startTls, keyStoreType);
+    }
+
+    @Substitute
+    static SslContext newClientContextInternal(
+            SslProvider provider,
+            Provider sslContextProvider,
+            X509Certificate[] trustCert, TrustManagerFactory trustManagerFactory,
+            X509Certificate[] keyCertChain, PrivateKey key, String keyPassword, KeyManagerFactory keyManagerFactory,
+            Iterable<String> ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn, String[] protocols,
+            long sessionCacheSize, long sessionTimeout, boolean enableOcsp, String keyStoreType) throws SSLException {
+        if (enableOcsp) {
+            throw new IllegalArgumentException("OCSP is not supported with this SslProvider: " + provider);
+        }
+        return (SslContext) (Object) new Target_io_netty_handler_ssl_JdkSslClientContext(sslContextProvider,
+                trustCert, trustManagerFactory, keyCertChain, key, keyPassword,
+                keyManagerFactory, ciphers, cipherFilter, apn, protocols, sessionCacheSize,
+                sessionTimeout, keyStoreType);
+    }
+
+}
+
+@TargetClass(className = "org.apache.kudu.shaded.io.netty.handler.ssl.JdkDefaultApplicationProtocolNegotiator")
+final class Target_io_netty_handler_ssl_JdkDefaultApplicationProtocolNegotiator {
+
+    @Alias
+    public static Target_io_netty_handler_ssl_JdkDefaultApplicationProtocolNegotiator INSTANCE;
+}
+
+@TargetClass(className = "org.apache.kudu.shaded.io.netty.handler.ssl.JdkSslContext")
+final class Target_io_netty_handler_ssl_JdkSslContext {
+
+    @Substitute
+    static JdkApplicationProtocolNegotiator toNegotiator(ApplicationProtocolConfig config, boolean isServer) {
+        if (config == null) {
+            return (JdkApplicationProtocolNegotiator) (Object) Target_io_netty_handler_ssl_JdkDefaultApplicationProtocolNegotiator.INSTANCE;
+        }
+
+        switch (config.protocol()) {
+        case NONE:
+            return (JdkApplicationProtocolNegotiator) (Object) Target_io_netty_handler_ssl_JdkDefaultApplicationProtocolNegotiator.INSTANCE;
+        case ALPN:
+            if (isServer) {
+                // GRAAL RC9 bug: https://github.com/oracle/graal/issues/813
+                //                switch(config.selectorFailureBehavior()) {
+                //                case FATAL_ALERT:
+                //                    return new JdkAlpnApplicationProtocolNegotiator(true, config.supportedProtocols());
+                //                case NO_ADVERTISE:
+                //                    return new JdkAlpnApplicationProtocolNegotiator(false, config.supportedProtocols());
+                //                default:
+                //                    throw new UnsupportedOperationException(new StringBuilder("JDK provider does not support ")
+                //                    .append(config.selectorFailureBehavior()).append(" failure behavior").toString());
+                //                }
+                SelectorFailureBehavior behavior = config.selectorFailureBehavior();
+                if (behavior == SelectorFailureBehavior.FATAL_ALERT)
+                    return new JdkAlpnApplicationProtocolNegotiator(true, config.supportedProtocols());
+                else if (behavior == SelectorFailureBehavior.NO_ADVERTISE)
+                    return new JdkAlpnApplicationProtocolNegotiator(false, config.supportedProtocols());
+                else {
+                    throw new UnsupportedOperationException(new StringBuilder("JDK provider does not support ")
+                            .append(config.selectorFailureBehavior()).append(" failure behavior").toString());
+                }
+            } else {
+                switch (config.selectedListenerFailureBehavior()) {
+                case ACCEPT:
+                    return new JdkAlpnApplicationProtocolNegotiator(false, config.supportedProtocols());
+                case FATAL_ALERT:
+                    return new JdkAlpnApplicationProtocolNegotiator(true, config.supportedProtocols());
+                default:
+                    throw new UnsupportedOperationException(new StringBuilder("JDK provider does not support ")
+                            .append(config.selectedListenerFailureBehavior()).append(" failure behavior").toString());
+                }
+            }
+        default:
+            throw new UnsupportedOperationException(
+                    new StringBuilder("JDK provider does not support ").append(config.protocol()).append(" protocol")
+                            .toString());
+        }
+    }
+
+}
+
+/*
+ * This one only prints exceptions otherwise we get a useless bogus
+ * exception message: https://github.com/eclipse-vertx/vert.x/issues/1657
+ */
+@TargetClass(className = "org.apache.kudu.shaded.io.netty.bootstrap.AbstractBootstrap")
+final class Target_io_netty_bootstrap_AbstractBootstrap {
+
+    @Alias
+    private ChannelFactory channelFactory;
+
+    @Alias
+    void init(Channel channel) throws Exception {
+    }
+
+    @Alias
+    public AbstractBootstrapConfig config() {
+        return null;
+    }
+
+    @Substitute
+    final ChannelFuture initAndRegister() {
+        Channel channel = null;
+        try {
+            channel = channelFactory.newChannel();
+            init(channel);
+        } catch (Throwable t) {
+            // THE FIX IS HERE:
+            t.printStackTrace();
+            if (channel != null) {
+                // channel can be null if newChannel crashed (eg SocketException("too many open files"))
+                channel.unsafe().closeForcibly();
+            }
+            // as the Channel is not registered yet we need to force the usage of the GlobalEventExecutor
+            return new DefaultChannelPromise(channel, GlobalEventExecutor.INSTANCE).setFailure(t);
+        }
+
+        ChannelFuture regFuture = config().group().register(channel);
+        if (regFuture.cause() != null) {
+            if (channel.isRegistered()) {
+                channel.close();
+            } else {
+                channel.unsafe().closeForcibly();
+            }
+        }
+
+        // If we are here and the promise is not failed, it's one of the following cases:
+        // 1) If we attempted registration from the event loop, the registration has been completed at this point.
+        //    i.e. It's safe to attempt bind() or connect() now because the channel has been registered.
+        // 2) If we attempted registration from the other thread, the registration request has been successfully
+        //    added to the event loop's task queue for later execution.
+        //    i.e. It's safe to attempt bind() or connect() now:
+        //         because bind() or connect() will be executed *after* the scheduled registration task is executed
+        //         because register(), bind(), and connect() are all bound to the same thread.
+
+        return regFuture;
+
+    }
+}
+
+@TargetClass(className = "org.apache.kudu.shaded.io.netty.channel.nio.NioEventLoop")
+final class Target_io_netty_channel_nio_NioEventLoop {
+
+    @Substitute
+    private static Queue<Runnable> newTaskQueue0(int maxPendingTasks) {
+        return new LinkedBlockingDeque<>();
+    }
+}
+
+@TargetClass(className = "org.apache.kudu.shaded.io.netty.buffer.AbstractReferenceCountedByteBuf")
+final class Target_io_netty_buffer_AbstractReferenceCountedByteBuf {
+
+    @Alias
+    @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.FieldOffset, name = "refCnt")
+    private static long REFCNT_FIELD_OFFSET;
+}
+
+@TargetClass(className = "org.apache.kudu.shaded.io.netty.util.AbstractReferenceCounted")
+final class Target_io_netty_util_AbstractReferenceCounted {
+
+    @Alias
+    @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.FieldOffset, name = "refCnt")
+    private static long REFCNT_FIELD_OFFSET;
+}
+
+// This class is runtime-initialized by NettyProcessor
+final class Holder_io_netty_util_concurrent_ScheduledFutureTask {
+    static final long START_TIME = System.nanoTime();
+}
+
+@TargetClass(className = "org.apache.kudu.shaded.io.netty.util.concurrent.ScheduledFutureTask")
+final class Target_io_netty_util_concurrent_ScheduledFutureTask {
+
+    // The START_TIME field is kept but not used.
+    // All the accesses to it have been replaced with Holder_io_netty_util_concurrent_ScheduledFutureTask
+
+    @Substitute
+    static long initialNanoTime() {
+        return Holder_io_netty_util_concurrent_ScheduledFutureTask.START_TIME;
+    }
+
+    @Substitute
+    static long nanoTime() {
+        return System.nanoTime() - Holder_io_netty_util_concurrent_ScheduledFutureTask.START_TIME;
+    }
+
+    @Alias
+    public long deadlineNanos() {
+        return 0;
+    }
+
+    @Substitute
+    public long delayNanos(long currentTimeNanos) {
+        return Math.max(0,
+                deadlineNanos() - (currentTimeNanos - Holder_io_netty_util_concurrent_ScheduledFutureTask.START_TIME));
+    }
+}
+
+@TargetClass(className = "org.apache.kudu.shaded.io.netty.channel.ChannelHandlerMask")
+final class Target_io_netty_channel_ChannelHandlerMask {
+
+    // Netty tries to self-optimized itself, but it requires lots of reflection. We disable this behavior and avoid
+    // misleading DEBUG messages in the log.
+    @Substitute
+    private static boolean isSkippable(final Class<?> handlerType, final String methodName, final Class... paramTypes) {
+        return false;
+    }
+}
+
+@TargetClass(className = "org.apache.kudu.shaded.io.netty.util.internal.NativeLibraryLoader")
+final class Target_io_netty_util_internal_NativeLibraryLoader {
+
+    // This method can trick GraalVM into thinking that Classloader#defineClass is getting called
+    @Substitute
+    static Class<?> tryToLoadClass(final ClassLoader loader, final Class<?> helper)
+            throws ClassNotFoundException {
+        return Class.forName(helper.getName(), false, loader);
+    }
+
+}
+
+@TargetClass(className = "org.apache.kudu.shaded.io.netty.buffer.EmptyByteBuf")
+final class Target_io_netty_buffer_EmptyByteBuf {
+
+    @Alias
+    @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.Reset)
+    private static ByteBuffer EMPTY_BYTE_BUFFER;
+
+    @Alias
+    @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.Reset)
+    private static long EMPTY_BYTE_BUFFER_ADDRESS;
+
+    @Substitute
+    public ByteBuffer nioBuffer() {
+        return EmptyByteBufStub.emptyByteBuffer();
+    }
+
+    @Substitute
+    public ByteBuffer[] nioBuffers() {
+        return new ByteBuffer[] { EmptyByteBufStub.emptyByteBuffer() };
+    }
+
+    @Substitute
+    public ByteBuffer internalNioBuffer(int index, int length) {
+        return EmptyByteBufStub.emptyByteBuffer();
+    }
+
+    @Substitute
+    public boolean hasMemoryAddress() {
+        return EmptyByteBufStub.emptyByteBufferAddress() != 0;
+    }
+
+    @Substitute
+    public long memoryAddress() {
+        if (hasMemoryAddress()) {
+            return EmptyByteBufStub.emptyByteBufferAddress();
+        } else {
+            throw new UnsupportedOperationException();
+        }
+    }
+
+}
+
+class NettySubstitutions {
+
+}
diff --git a/extensions/kudu/runtime/src/main/java/org/apache/camel/quarkus/component/kudu/graal/ZLibSubstitutions.java b/extensions/kudu/runtime/src/main/java/org/apache/camel/quarkus/component/kudu/graal/ZLibSubstitutions.java
new file mode 100644
index 0000000..9e80749
--- /dev/null
+++ b/extensions/kudu/runtime/src/main/java/org/apache/camel/quarkus/component/kudu/graal/ZLibSubstitutions.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 org.apache.camel.quarkus.component.kudu.graal;
+
+import com.oracle.svm.core.annotate.Substitute;
+import com.oracle.svm.core.annotate.TargetClass;
+import org.apache.kudu.shaded.io.netty.handler.codec.compression.JdkZlibDecoder;
+import org.apache.kudu.shaded.io.netty.handler.codec.compression.JdkZlibEncoder;
+import org.apache.kudu.shaded.io.netty.handler.codec.compression.ZlibDecoder;
+import org.apache.kudu.shaded.io.netty.handler.codec.compression.ZlibEncoder;
+import org.apache.kudu.shaded.io.netty.handler.codec.compression.ZlibWrapper;
+
+/**
+ * This substitution avoid having jcraft zlib added to the build
+ * Adapted from
+ * https://github.com/quarkusio/quarkus/blob/master/extensions/netty/runtime/src/main/java/io/quarkus/netty/runtime/graal/ZLibSubstitutions.java
+ */
+@TargetClass(className = "org.apache.kudu.shaded.io.netty.handler.codec.compression.ZlibCodecFactory")
+final class Target_io_netty_handler_codec_compression_ZlibCodecFactory {
+
+    @Substitute
+    public static ZlibEncoder newZlibEncoder(int compressionLevel) {
+        return new JdkZlibEncoder(compressionLevel);
+    }
+
+    @Substitute
+    public static ZlibEncoder newZlibEncoder(ZlibWrapper wrapper) {
+        return new JdkZlibEncoder(wrapper);
+    }
+
+    @Substitute
+    public static ZlibEncoder newZlibEncoder(ZlibWrapper wrapper, int compressionLevel) {
+        return new JdkZlibEncoder(wrapper, compressionLevel);
+    }
+
+    @Substitute
+    public static ZlibEncoder newZlibEncoder(ZlibWrapper wrapper, int compressionLevel, int windowBits, int memLevel) {
+        return new JdkZlibEncoder(wrapper, compressionLevel);
+    }
+
+    @Substitute
+    public static ZlibEncoder newZlibEncoder(byte[] dictionary) {
+        return new JdkZlibEncoder(dictionary);
+    }
+
+    @Substitute
+    public static ZlibEncoder newZlibEncoder(int compressionLevel, byte[] dictionary) {
+        return new JdkZlibEncoder(compressionLevel, dictionary);
+    }
+
+    @Substitute
+    public static ZlibEncoder newZlibEncoder(int compressionLevel, int windowBits, int memLevel, byte[] dictionary) {
+        return new JdkZlibEncoder(compressionLevel, dictionary);
+    }
+
+    @Substitute
+    public static ZlibDecoder newZlibDecoder() {
+        return new JdkZlibDecoder();
+    }
+
+    @Substitute
+    public static ZlibDecoder newZlibDecoder(ZlibWrapper wrapper) {
+        return new JdkZlibDecoder(wrapper);
+    }
+
+    @Substitute
+    public static ZlibDecoder newZlibDecoder(byte[] dictionary) {
+        return new JdkZlibDecoder(dictionary);
+    }
+}
+
+class ZLibSubstitutions {
+
+}