Skip to content

[GR-45893] jdk.net.ExtendedSocketOptions.TCP_KEEPIDLE not available in native-image application #6457

Closed
@beckermarc

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 java.base@17.0.6/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

  1. Unpack the application: tcp-keepidle-repro.zip
  2. mvn native:compile
  3. java -jar target/tcp-keepaliveidle-0.0.1-SNAPSHOT.jar -> works
  4. target/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

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions