-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Description
I am facing issues using jdk.net.ExtendedSocketOptions.TCP_KEEPIDLE in native images. The following code runs fine on a JVM, but fails in a native image:
AsynchronousSocketChannel socket = AsynchronousSocketChannel.open();
socket.setOption(jdk.net.ExtendedSocketOptions.TCP_KEEPIDLE, 100);Error in native-image:
Exception in thread "main" java.lang.UnsupportedOperationException: 'TCP_KEEPIDLE' not supported
at [email protected]/sun.nio.ch.AsynchronousSocketChannelImpl.setOption(AsynchronousSocketChannelImpl.java:461)
at com.example.repro.Application.main(Application.java:15)
The class jdk.net.ExtendedSocketOptions registers some platform-dependent optionally available socket options. All of this is orchestrated by sun.net.ext.ExtendedSocketOptions, which dynamically loads jdk.net.ExtendedSocketOptions if available. jdk.net.ExtendedSocketOptions then performs initialization of these additional options in a static code block.
For some reason, this static code block is not properly executed in the native-image. I know about build-time initialization of classes in native-images, but do not fully understand if this has an impact here.
To enable dynamic lookup of jdk.net.ExtendedSocketOptions I also put the following information into a reflect-config.json:
[
{
"name": "jdk.net.ExtendedSocketOptions"
}
]Below I have provided a simple application to reproduce the issue. There I have provided additional debug output, which checks the conditions that check some boundary conditions for the exception to occur:
AsynchronousSocketChannel socket = AsynchronousSocketChannel.open();
Set<SocketOption<?>> options = socket.supportedOptions();
System.out.println("Has TCP_KEEPIDLE? " + options.contains(jdk.net.ExtendedSocketOptions.TCP_KEEPIDLE));
System.out.println("Options: " + options);Interestingly this produces the following output in a native-image:
Has TCP_KEEPIDLE? false
Options: [TCP_NODELAY, TCP_KEEPCOUNT, TCP_KEEPINTERVAL, SO_REUSEADDR, SO_SNDBUF, SO_RCVBUF, TCP_KEEPIDLE, SO_INCOMING_NAPI_ID, TCP_QUICKACK, SO_KEEPALIVE, SO_REUSEPORT]
Notice that the contains check evaluates to false, however the stringified options DO INCLUDE TCP_KEEPIDLE. Maybe this helps in finding the issue. My guess is this has something to do with build-time class initialization and code optimization, but I don't fully understand this behaviour.
Steps to reproduce the issue
Please include both build steps as well as run steps
- Unpack the application: tcp-keepidle-repro.zip
mvn native:compilejava -jar target/tcp-keepaliveidle-0.0.1-SNAPSHOT.jar-> workstarget/tcp-keepaliveidle-> fails
Describe GraalVM and your environment:
- GraalVM version:
OpenJDK 64-Bit Server VM GraalVM CE 17.0.7-dev+4.1 (build 17.0.7+4-jvmci-23.0-b10, mixed mode, sharing) - JDK major version:
17 - OS: Ubuntu 22.04
- Architecture: AMD64