I am trying to generate a native image with GraalVM using the graalvmNative
plugin in Gradle. With simple projects, it works fine when I just apply the org.graalvm.buildtools
plugin. However, when I need to add other dependencies like netty-transport-4.1.109.Final
and netty-resolver-4.1.109.Final
, I get stuck in a loop of tracing and setting individual classes to initialize at runtime, as shown in the following Gradle configuration:
graalvmNative {
toolchainDetection = true
binaries {
main {
agent {
buildArgs.add('--strict-image-heap')
buildArgs.add("--trace-object-instantiation=com.sun.jmx.mbeanserver.JmxMBeanServer")
buildArgs.add('--trace-object-instantiation=java.net.Inet4Address')
buildArgs.add('--trace-class-initialization=io.netty.util.internal.SystemPropertyUtil')
buildArgs.add('--trace-class-initialization=io.netty.util.internal.PlatformDependent')
buildArgs.add('--enable-url-protocols=http,https')
buildArgs.add('--verbose')
buildArgs.add('--trace-class-initialization=org.apache.commons.logging.LogFactory')
buildArgs.add('-H:+ReportExceptionStackTraces') // to print stacktrace of underlying exception
// buildArgs.add('--initialize-at-build-time=org.springframework.data.repository.util.QueryExecutionConverters')
// io.netty should be at run time only
buildArgs.add('--initialize-at-run-time=io.netty.util.NetUtil')
buildArgs.add('--initialize-at-run-time=io.netty.util.ResourceLeakDetectorFactory')
buildArgs.add('--initialize-at-run-time=io.netty.handler.ssl.SslHandler')
buildArgs.add('--initialize-at-run-time=io.netty.buffer.AbstractByteBuf')
buildArgs.add('--initialize-at-run-time=io.netty.util.internal.CleanerJava6')
buildArgs.add('--initialize-at-run-time=io.netty.buffer.Unpooled')
buildArgs.add('--initialize-at-run-time=io.netty.channel.ChannelHandlerMask')
buildArgs.add('--initialize-at-run-time=io.netty.util.Recycler')
buildArgs.add('--initialize-at-run-time=io.netty.resolver.HostsFileEntriesResolver')
buildArgs.add('--initialize-at-run-time=io.netty.util.internal.CleanerJava9')
//
buildArgs.add('--initialize-at-run-time=io.netty.bootstrap.Bootstrap')
buildArgs.add('--initialize-at-run-time=io.netty.util.concurrent.FastThreadLocalThread')
buildArgs.add('--initialize-at-run-time=io.netty.util.internal.MacAddressUtil')
buildArgs.add('--initialize-at-run-time=io.netty.channel.DefaultChannelId')
buildArgs.add('--initialize-at-run-time=io.netty.channel.DefaultChannelPipeline')
buildArgs.add('--initialize-at-run-time=io.netty.util.internal.PlatformDependent0')
buildArgs.add('--initialize-at-run-time=io.netty.util.internal.InternalThreadLocalMap')
buildArgs.add('--initialize-at-run-time=io.netty.buffer.AbstractByteBufAllocator')
buildArgs.add('--initialize-at-run-time=io.netty.util.concurrent.DefaultPromise')
buildArgs.add('--initialize-at-run-time=io.netty.util.internal.StringUtil')
buildArgs.add('--initialize-at-run-time=io.netty.util.AttributeKey')
buildArgs.add('--initialize-at-run-time=io.netty.util.internal.SystemPropertyUtil')
buildArgs.add('--initialize-at-run-time=io.netty.channel.ChannelInitializer')
buildArgs.add('--initialize-at-run-time=io.netty.channel.socket.nio.SelectorProviderUtil')
buildArgs.add('--initialize-at-run-time=io.netty.channel.AbstractChannel')
buildArgs.add('--initialize-at-run-time=io.netty.util.internal.PlatformDependent')
buildArgs.add('--initialize-at-run-time=io.netty.channel.DefaultFileRegion')
buildArgs.add('--initialize-at-run-time=io.netty.channel.epoll.Native')
buildArgs.add('--initialize-at-run-time=io.netty.channel.epoll.Epoll')
buildArgs.add('--initialize-at-run-time=io.netty.channel.epoll.EpollEventLoop')
buildArgs.add('--initialize-at-run-time=io.netty.channel.epoll.EpollEventArray')
buildArgs.add('--initialize-at-run-time=io.netty.channel.kqueue.KQueue')
buildArgs.add('--initialize-at-run-time=io.netty.channel.kqueue.KQueueEventLoop')
buildArgs.add('--initialize-at-run-time=io.netty.channel.kqueue.KQueueEventArray')
buildArgs.add('--initialize-at-run-time=io.netty.channel.kqueue.Native')
buildArgs.add('--initialize-at-run-time=io.netty.channel.unix.Limits')
buildArgs.add('--initialize-at-run-time=io.netty.channel.unix.Errors')
buildArgs.add('--initialize-at-run-time=io.netty.channel.unix.IovArray')
buildArgs.add('--initialize-at-run-time=io.netty.handler.ssl.BouncyCastleAlpnSslUtils')
buildArgs.add('--initialize-at-run-time=io.netty.incubator.codec.quic.InsecureQuicTokenHandler')
buildArgs.add('--initialize-at-run-time=io.netty.incubator.codec.quic.SecureRandomQuicConnectionIdGenerator')
}
}
}
I am using graalvm-jdk-17_linux-x64_bin with Spring Boot 3.2.5 and the Gradle plugin version id ‘org.graalvm.buildtools.native’ version ‘0.9.28’.
Instead of listing individual classes, is there a way to configure Gradle to initialize entire modules or dependencies at runtime when generating the native image? This would make the configuration more concise and maintainable, especially when working with large third-party libraries like Netty.
I tried searching for solutions, but I couldn’t find a way to achieve this. Any help or guidance would be greatly appreciated.