netty: Missing graalvm native image reflection hints for SelectorProvider
Expected behavior
Netty should cover all graalvm native image reflection hints
Actual behavior
Although there are configuration for java.lang.management.ManagementFactory and java.lang.management.RuntimeMXBean etc. But not include java.nio.channels.spi.SelectorProvide which is invoke by reflection in SelectorProviderUtil
Netty code in io.netty.channel.socket.nio.SelectorProviderUtil:
@SuppressJava6Requirement(reason = "Usage guarded by java version check")
static Method findOpenMethod(String methodName) {
if (PlatformDependent.javaVersion() >= 15) {
try {
return SelectorProvider.class.getMethod(methodName, java.net.ProtocolFamily.class);
} catch (Throwable e) {
logger.debug("SelectorProvider.{}(ProtocolFamily) not available, will use default", methodName, e);
}
}
return null;
}
In fact, Netty will use SelectorProviderUtil.findOpenMethod to find and invoke reflective two methods in SelectorProvider in a Spring application:
public SocketChannel openSocketChannel(ProtocolFamily family)
public ServerSocketChannel openServerSocketChannel(ProtocolFamily family)
Steps to reproduce
After compiled a Spring application to graalvm native image, and set log level for io.netty to TRACE, such exception will show up(which can’t reproduce in jvm application):
2023-08-31T01:27:05.755+08:00 TRACE 55266 --- [ main] io.netty.channel.nio.NioEventLoop : instrumented a special java.util.Set into: sun.nio.ch.EPollSelectorImpl@28fee399
2023-08-31T01:27:05.755+08:00 DEBUG 55266 --- [ main] i.n.c.socket.nio.SelectorProviderUtil : SelectorProvider.openServerSocketChannel(ProtocolFamily) not available, will use default
java.lang.NoSuchMethodException: java.nio.channels.spi.SelectorProvider.openServerSocketChannel(java.net.ProtocolFamily)
at java.base@17.0.8/java.lang.Class.checkMethod(DynamicHub.java:1038) ~[monolith-service:na]
at java.base@17.0.8/java.lang.Class.getMethod(DynamicHub.java:1023) ~[monolith-service:na]
at io.netty.channel.socket.nio.SelectorProviderUtil.findOpenMethod(SelectorProviderUtil.java:39) ~[na:na]
at io.netty.channel.socket.nio.NioServerSocketChannel.<clinit>(NioServerSocketChannel.java:57) ~[monolith-service:4.1.97.Final]
at reactor.netty.resources.DefaultLoopNIO.getChannel(DefaultLoopNIO.java:45) ~[na:na]
at reactor.netty.resources.LoopResources.onChannel(LoopResources.java:243) ~[monolith-service:1.1.10]
at reactor.netty.tcp.TcpResources.onChannel(TcpResources.java:251) ~[monolith-service:1.1.10]
at reactor.netty.transport.TransportConfig.lambda$connectionFactory$1(TransportConfig.java:277) ~[monolith-service:1.1.10]
at reactor.netty.transport.TransportConnector.doInitAndRegister(TransportConnector.java:277) ~[na:na]
at reactor.netty.transport.TransportConnector.bind(TransportConnector.java:87) ~[na:na]
at reactor.netty.transport.ServerTransport.lambda$bind$0(ServerTransport.java:115) ~[monolith-service:1.1.10]
at reactor.core.publisher.MonoCreate.subscribe(MonoCreate.java:58) ~[na:na]
at reactor.core.publisher.Mono.subscribe(Mono.java:4495) ~[monolith-service:3.5.9]
at reactor.core.publisher.Mono.block(Mono.java:1737) ~[monolith-service:3.5.9]
at reactor.netty.transport.ServerTransport.bindNow(ServerTransport.java:149) ~[monolith-service:1.1.10]
at reactor.netty.transport.ServerTransport.bindNow(ServerTransport.java:134) ~[monolith-service:1.1.10]
at org.springframework.boot.web.embedded.netty.NettyWebServer.startHttpServer(NettyWebServer.java:145) ~[monolith-service:3.1.3]
at org.springframework.boot.web.embedded.netty.NettyWebServer.start(NettyWebServer.java:100) ~[monolith-service:3.1.3]
at org.springframework.boot.web.reactive.context.WebServerManager.start(WebServerManager.java:55) ~[na:na]
at org.springframework.boot.web.reactive.context.WebServerStartStopLifecycle.start(WebServerStartStopLifecycle.java:41) ~[na:na]
at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:179) ~[monolith-service:6.0.11]
at org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup.start(DefaultLifecycleProcessor.java:357) ~[monolith-service:6.0.11]
at java.base@17.0.8/java.lang.Iterable.forEach(Iterable.java:75) ~[monolith-service:na]
at org.springframework.context.support.DefaultLifecycleProcessor.startBeans(DefaultLifecycleProcessor.java:156) ~[monolith-service:6.0.11]
at org.springframework.context.support.DefaultLifecycleProcessor.onRefresh(DefaultLifecycleProcessor.java:124) ~[monolith-service:6.0.11]
at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:958) ~[monolith-service:6.0.11]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:611) ~[monolith-service:6.0.11]
at org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext.refresh(ReactiveWebServerApplicationContext.java:66) ~[monolith-service:3.1.3]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:734) ~[monolith-service:3.1.3]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:436) ~[monolith-service:3.1.3]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:312) ~[monolith-service:3.1.3]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306) ~[monolith-service:3.1.3]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295) ~[monolith-service:3.1.3]
at com.hkmci.masterspace.monolith.ApplicationKt.main(Application.kt:15) ~[monolith-service:na]
at com.hkmci.masterspace.monolith.ApplicationKt.main(Application.kt) ~[monolith-service:na]
Minimal yet complete reproducer code (or URL to code)
Create a empty Webflux Spring application with Spring Initializr and compile to native image.
set log level of io.netty to TRACE.
Just run the application, the exception above will show up.
Netty version
4.1.97.Final
JVM version (e.g. java -version)
GraalVM for JDK 17 Community 17.0.8(native image)
OS version (e.g. uname -a)
Ubuntu22.04
About this issue
- Original URL
- State: closed
- Created 10 months ago
- Comments: 15 (9 by maintainers)
I create PR in graalvm-reachability-metadata: https://github.com/oracle/graalvm-reachability-metadata/pull/382
@czp3009 I think this should be enough, can you test it?