During the graalvm native compile, the Spring provided Feature org.springframework.aot.nativex.feature.PreComputeFieldFeature will lead to all Netty native transports unavailable.

all reactor-netty related log during compile:

Field reactor.netty.internal.util.Metrics#isMicrometerAvailable set to false at build time
Field reactor.netty.internal.util.Metrics#isTracingAvailable set to false at build time
Field reactor.netty.resources.DefaultLoopIOUring#isIoUringAvailable set to false at build time
Field reactor.netty.resources.DefaultLoopEpoll#isEpollAvailable set to false at build time
Field reactor.netty.resources.DefaultLoopKQueue#isKqueueAvailable set to false at build time
Field reactor.netty.http.server.HAProxyMessageReader#isProxyProtocolAvailable set to false at build time

This is due to org.springframework.aot.nativex.feature.PreComputeFieldFeature contains such a field match pattern: https://github.com/spring-projects/spring-framework/blob/32f128b6ba118ea42f6648cda94ed1de7afa75aa/spring-core/src/main/java/org/springframework/aot/nativex/feature/PreComputeFieldFeature.java#L48C4-L48C4

Pattern.compile(Pattern.quote("reactor.") + ".*#.*Available")

This causes all the properties used by reator-netty to detect native transports to be selected.

All those properties should be init at runtime not build time to let reactor-netty correctly chose netty native transport.

This problem cause broken of using r2dbc with unix domain socket on native image.

I'm not familiar with pattern, but I think it's a good idea to skip the reactor netty properties to fix this issue.

Comment From: sdeleuze

will lead to all Netty native transports unavailable

Could you please elaborate on what conditions more specially are false at build time but true at runtime (closed wold assumptions means that the classpath is fixed at build time and native image nature means the Operating System will be the same)?

This problem cause broken of using r2dbc with unix domain socket on native image.

Could you please share more details about the problem and a reproducer?

Comment From: czp3009

@sdeleuze When i building appliaction on a Ubuntu22.04 machine(same as runtime machine), reactor-netty native transport conditions in the logs above will always be false:

Field reactor.netty.resources.DefaultLoopIOUring#isIoUringAvailable set to false at build time
Field reactor.netty.resources.DefaultLoopEpoll#isEpollAvailable set to false at build time
Field reactor.netty.resources.DefaultLoopKQueue#isKqueueAvailable set to false at build time

Please focus on the reactor.netty.resources.DefaultLoopEpoll. in general, epoll is always available on a linux machine. But org.springframework.aot.nativex.feature.PreComputeFieldFeature disabled it.

Please see the code of DefaultLoopEpoll:

static final boolean isEpollAvailable;

static {
    boolean epollCheck = false;
    try {
        Class.forName("io.netty.channel.epoll.Epoll");
        epollCheck = Epoll.isAvailable();
    }
    catch (ClassNotFoundException cnfe) {
        // noop
     }
    isEpollAvailable = epollCheck;
    if (log.isDebugEnabled()) {
        log.debug("Default Epoll support : " + isEpollAvailable);
    }
}

ThrowawayClassLoader always get the value of this field as false.

After the field is always baked to false at compile time, epoll support will be disabled in runtime. Thus cause unix domain socket unavailable.

As mentioned above, this problem not only affect Epoll(on Linux), also affect other netty native transport such as KQueue(on Mac). all of these field is baked to false.

If that's still not clear enough, I can provide a sample application to reproduce it.

Comment From: sdeleuze

Could be a missing reflection entry for io.netty.channel.epoll.Epoll. Could you please try to add a src/main/resources/META-INF/native-image/reflect-config.json file on your project with the following content:

[
  {
    "name": "io.netty.channel.epoll.Epoll"
  }
]

Could you please try with that let me know if it helps? If it does, we can probably ask Reactor team to add such metadata.

Comment From: czp3009

@sdeleuze if i use Epoll.isAvailable() in my code, this line always return true, but the log above still says reactor.netty.resources.DefaultLoopEpoll#isEpollAvailable set to false at build time, and the still Epoll broken.

This means that it's not that Epoll can't be reflected, it's that the Field isEpollAvailable in reactor.netty.resources.DefaultLoopEpoll backed incorrectly.

i will give you a sample application later

Comment From: sdeleuze

if i use Epoll.isAvailable() in my code, this line always return true

This is my expectation as well, but what I suspect is that on native without a proper reflection entry, Class.forName("io.netty.channel.epoll.Epoll") will throw a ClassNotFoundException and DefaultLoopEpoll#isEpollAvailable will be false.

That said, it could also be inlined and not require reflection metadata, so let's see with your repro.

Comment From: czp3009

@sdeleuze I create a demo: https://github.com/czp3009/r2dbc-native-image-domain-socket-issue-reproduce

Please follow the README to locate problem