Skip to content

Embedded Jetty Native Websocket Server fails at runtime on native-image #4016

@hogfilho

Description

@hogfilho

Describe the issue
Hello! When I try to run a minimal example of embedded Jetty websocket server, it fails at runtime when a client connects if I compile it using native-image.
This repository contains the minimal server example:
https://github.com/jetty-project/embedded-jetty-websocket-examples
it contais two projects.

  • javax.websocket-example - This one uses javax.websocket apis and works fine on native-image
  • native-jetty-websocket-example - This one uses org.eclipse.jetty.websocket apis, compiles fine using native-image, but fails at runtime, maybe due to MethodHandler issues?

I wrote my application using org.eclipse.jetty.websocket apis, and I would like to build a working native image.

Steps to reproduce the issue

  1. git clone https://github.com/jetty-project/embedded-jetty-websocket-examples.git
  2. build native-jetty-websocket-example
  3. run native-image-agent on org.eclipse.jetty.demo.EventServer -> websocket server works fine on this step
  4. generate native-image binary of org.eclipse.jetty.demo.EventServer
  5. run the generated native image
  6. connect to localhost on port 8080 via websocket
  7. see the errors on console, the websocket client is disconnected immediately after connect

Describe GraalVM and your environment:

  • openjdk version "17.0.1" 2021-10-19
  • OpenJDK Runtime Environment GraalVM CE 21.3.0 (build 17.0.1+12-jvmci-21.3-b05)
  • OpenJDK 64-Bit Server VM GraalVM CE 21.3.0 (build 17.0.1+12-jvmci-21.3-b05, mixed mode, sharing)
  • OS: Arch Linux
  • Architecture: AMD64

More details

  • build native-image of websocket server using --native-image-info and --verbose:
Apply file:///tmp/native/META-INF/native-image/jni-config.json
Apply file:///tmp/native/META-INF/native-image/reflect-config.json
Apply file:///tmp/native/META-INF/native-image/resource-config.json
Apply file:///tmp/native/META-INF/native-image/proxy-config.json
Apply file:///tmp/native/META-INF/native-image/serialization-config.json
Apply file:///tmp/native/META-INF/native-image/predefined-classes-config.json
Executing [
/home/helder/Downloads/graalvm-ce-java17-21.3.0/bin/java \
-XX:+UseParallelGC \
-XX:+UnlockExperimentalVMOptions \
-XX:+EnableJVMCI \
-Dtruffle.TrustAllTruffleRuntimeProviders=true \
-Dtruffle.TruffleRuntime=com.oracle.truffle.api.impl.DefaultTruffleRuntime \
-Dgraalvm.ForcePolyglotInvalid=true \
-Dgraalvm.locatorDisabled=true \
-Dsubstratevm.IgnoreGraalVersionCheck=true \
--add-exports=java.base/com.sun.crypto.provider=ALL-UNNAMED \
--add-exports=java.base/jdk.internal.access.foreign=ALL-UNNAMED \
--add-exports=java.base/jdk.internal.event=ALL-UNNAMED \
--add-exports=java.base/jdk.internal.loader=ALL-UNNAMED \
--add-exports=java.base/jdk.internal.logger=ALL-UNNAMED \
--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED \
--add-exports=java.base/jdk.internal.module=ALL-UNNAMED \
--add-exports=java.base/jdk.internal.org.objectweb.asm=ALL-UNNAMED \
--add-exports=java.base/jdk.internal.org.xml.sax.helpers=ALL-UNNAMED \
--add-exports=java.base/jdk.internal.perf=ALL-UNNAMED \
--add-exports=java.base/jdk.internal.platform=ALL-UNNAMED \
--add-exports=java.base/jdk.internal.ref=ALL-UNNAMED \
--add-exports=java.base/jdk.internal.reflect=ALL-UNNAMED \
--add-exports=java.base/jdk.internal.util.xml.impl=ALL-UNNAMED \
--add-exports=java.base/jdk.internal.util.xml=ALL-UNNAMED \
--add-exports=java.base/sun.invoke.util=ALL-UNNAMED \
--add-exports=java.base/sun.nio.ch=ALL-UNNAMED \
--add-exports=java.base/sun.reflect.annotation=ALL-UNNAMED \
--add-exports=java.base/sun.reflect.generics.reflectiveObjects=ALL-UNNAMED \
--add-exports=java.base/sun.reflect.generics.repository=ALL-UNNAMED \
--add-exports=java.base/sun.reflect.generics.tree=ALL-UNNAMED \
--add-exports=java.base/sun.security.jca=ALL-UNNAMED \
--add-exports=java.base/sun.security.provider=ALL-UNNAMED \
--add-exports=java.base/sun.security.util=ALL-UNNAMED \
--add-exports=java.base/sun.text.spi=ALL-UNNAMED \
--add-exports=java.base/sun.util.calendar=ALL-UNNAMED \
--add-exports=java.base/sun.util.locale.provider=ALL-UNNAMED \
--add-exports=java.base/sun.util.resources=ALL-UNNAMED \
--add-exports=java.xml.crypto/org.jcp.xml.dsig.internal.dom=ALL-UNNAMED \
--add-exports=jdk.internal.vm.ci/jdk.vm.ci.aarch64=ALL-UNNAMED \
--add-exports=jdk.internal.vm.ci/jdk.vm.ci.amd64=ALL-UNNAMED \
--add-exports=jdk.internal.vm.ci/jdk.vm.ci.code.site=ALL-UNNAMED \
--add-exports=jdk.internal.vm.ci/jdk.vm.ci.code.stack=ALL-UNNAMED \
--add-exports=jdk.internal.vm.ci/jdk.vm.ci.code=ALL-UNNAMED \
--add-exports=jdk.internal.vm.ci/jdk.vm.ci.common=ALL-UNNAMED \
--add-exports=jdk.internal.vm.ci/jdk.vm.ci.hotspot.aarch64=ALL-UNNAMED \
--add-exports=jdk.internal.vm.ci/jdk.vm.ci.hotspot.amd64=ALL-UNNAMED \
--add-exports=jdk.internal.vm.ci/jdk.vm.ci.hotspot=ALL-UNNAMED \
--add-exports=jdk.internal.vm.ci/jdk.vm.ci.meta=ALL-UNNAMED \
--add-exports=jdk.internal.vm.ci/jdk.vm.ci.runtime=ALL-UNNAMED \
--add-exports=jdk.internal.vm.ci/jdk.vm.ci.services=ALL-UNNAMED \
--add-exports=jdk.jfr/jdk.jfr.events=ALL-UNNAMED \
--add-exports=jdk.jfr/jdk.jfr.internal.consumer=ALL-UNNAMED \
--add-exports=jdk.jfr/jdk.jfr.internal.handlers=ALL-UNNAMED \
--add-exports=jdk.jfr/jdk.jfr.internal.jfc=ALL-UNNAMED \
--add-exports=jdk.jfr/jdk.jfr.internal=ALL-UNNAMED \
-XX:+UseJVMCINativeLibrary \
-Xss10m \
-Xms1g \
-Xmx13367069896 \
-Duser.country=US \
-Duser.language=en \
-Djava.awt.headless=true \
-Dorg.graalvm.version=21.3.0 \
-Dorg.graalvm.config=CE \
-Dcom.oracle.graalvm.isaot=true \
-Djava.system.class.loader=com.oracle.svm.hosted.NativeImageSystemClassLoader \
-Xshare:off \
-Djdk.internal.lambda.disableEagerInitialization=true \
-Djdk.internal.lambda.eagerlyInitialize=false \
-Djava.lang.invoke.InnerClassLambdaMetafactory.initializeLambdas=false \
-javaagent:/home/helder/Downloads/graalvm-ce-java17-21.3.0/lib/svm/builder/svm.jar \
-cp \
/home/helder/Downloads/graalvm-ce-java17-21.3.0/lib/svm/builder/javacpp-shadowed.jar:/home/helder/Downloads/graalvm-ce-java17-21.3.0/lib/svm/builder/svm.jar:/home/helder/Downloads/graalvm-ce-java17-21.3.0/lib/svm/builder/svm-llvm.jar:/home/helder/Downloads/graalvm-ce-java17-21.3.0/lib/svm/builder/llvm-platform-specific-shadowed.jar:/home/helder/Downloads/graalvm-ce-java17-21.3.0/lib/svm/builder/objectfile.jar:/home/helder/Downloads/graalvm-ce-java17-21.3.0/lib/svm/builder/llvm-wrapper-shadowed.jar:/home/helder/Downloads/graalvm-ce-java17-21.3.0/lib/svm/builder/pointsto.jar \
--module-path \
/home/helder/Downloads/graalvm-ce-java17-21.3.0/lib/truffle/truffle-api.jar \
'com.oracle.svm.hosted.NativeImageGeneratorRunner$JDK9Plus' \
-watchpid \
155488 \
-imagecp \
/tmp/native:/tmp/native/wsserverjetty.jar:/home/helder/Downloads/graalvm-ce-java17-21.3.0/lib/svm/library-support.jar \
-H:Path=/tmp/native \
-H:+DumpTargetInfo \
'-H:Class@manifest from file:///tmp/native/wsserverjetty.jar=br.com.hfilho.jettytest.EventServer' \
'-H:Name@manifest from file:///tmp/native/wsserverjetty.jar=wsserverjetty' \
-H:JNIConfigurationResources@file:///tmp/native/META-INF/native-image/jni-config.json=META-INF/native-image/jni-config.json \
-H:ReflectionConfigurationResources@file:///tmp/native/META-INF/native-image/reflect-config.json=META-INF/native-image/reflect-config.json \
-H:ResourceConfigurationResources@file:///tmp/native/META-INF/native-image/resource-config.json=META-INF/native-image/resource-config.json \
-H:DynamicProxyConfigurationResources@file:///tmp/native/META-INF/native-image/proxy-config.json=META-INF/native-image/proxy-config.json \
-H:SerializationConfigurationResources@file:///tmp/native/META-INF/native-image/serialization-config.json=META-INF/native-image/serialization-config.json \
-H:PredefinedClassesConfigurationResources@file:///tmp/native/META-INF/native-image/predefined-classes-config.json=META-INF/native-image/predefined-classes-config.json \
-H:CLibraryPath=/home/helder/Downloads/graalvm-ce-java17-21.3.0/lib/svm/clibraries/linux-amd64
]
[wsserverjetty:155509]    classlist:     767.94 ms,  0.96 GB
[wsserverjetty:155509]        (cap):     382.76 ms,  0.96 GB
[wsserverjetty:155509]        setup:   1,438.12 ms,  0.96 GB
# Printing compilation-target information to: /tmp/native/reports/target_info_20211114_213040.txt
[wsserverjetty:155509]     (clinit):     211.20 ms,  2.37 GB
# Printing native-library information to: /tmp/native/reports/native_library_info_20211114_213052.txt
[wsserverjetty:155509]   (typeflow):   3,338.28 ms,  2.37 GB
[wsserverjetty:155509]    (objects):   6,989.30 ms,  2.37 GB
[wsserverjetty:155509]   (features):   1,630.13 ms,  2.37 GB
[wsserverjetty:155509]     analysis:  12,676.45 ms,  2.37 GB
[wsserverjetty:155509]     universe:     870.29 ms,  2.37 GB
[wsserverjetty:155509]      (parse):     638.41 ms,  3.56 GB
[wsserverjetty:155509]     (inline):     864.67 ms,  3.56 GB
[wsserverjetty:155509]    (compile):  11,270.84 ms,  4.83 GB
[wsserverjetty:155509]      compile:  14,082.32 ms,  4.83 GB
[wsserverjetty:155509]        image:   1,356.56 ms,  4.83 GB
[wsserverjetty:155509]        write:     215.30 ms,  4.83 GB
[wsserverjetty:155509]      [total]:  31,580.48 ms,  4.83 GB
# Printing build artifacts to: /tmp/native/wsserverjetty.build_artifacts.txt
  • Here is the log of WebsocketServer native-image after a client connection
2021-11-14 21:38:51.702:INFO :oejs.Server:main: jetty-10.0.7; built: 2021-10-06T19:34:02.766Z; git: da8a4553af9dd84080931fa0f8c678cd2d60f3d9; jvm 17.0.1
2021-11-14 21:38:51.703:INFO :oejss.DefaultSessionIdManager:main: Session workerName=node0
2021-11-14 21:38:51.703:INFO :oejsh.ContextHandler:main: Started o.e.j.s.ServletContextHandler@1c547e5a{/,null,AVAILABLE}
2021-11-14 21:38:51.703:INFO :oejs.AbstractConnector:main: Started ServerConnector@36773a20{HTTP/1.1, (http/1.1)}{0.0.0.0:6001}
2021-11-14 21:38:51.703:INFO :oejs.Server:main: Started Server@37942616{STARTING}[10.0.7,sto=0] @2ms
Use Ctrl+C to stop server
org.eclipse.jetty.websocket.api.exceptions.CloseException: org.eclipse.jetty.websocket.core.exception.WebSocketException: EventSocket OPEN method error: Invalid MethodHandle void([B, int, int) - expected void([B, int, int)
        at org.eclipse.jetty.websocket.common.JettyWebSocketFrameHandler.convertCause(JettyWebSocketFrameHandler.java:506)
        at org.eclipse.jetty.websocket.common.JettyWebSocketFrameHandler.onError(JettyWebSocketFrameHandler.java:258)
        at org.eclipse.jetty.websocket.core.internal.WebSocketCoreSession.lambda$closeConnection$2(WebSocketCoreSession.java:280)
        at org.eclipse.jetty.server.handler.ContextHandler.handle(ContextHandler.java:1445)
        at org.eclipse.jetty.server.handler.ContextHandler.handle(ContextHandler.java:1482)
        at org.eclipse.jetty.websocket.core.server.internal.AbstractHandshaker$1.handle(AbstractHandshaker.java:212)
        at org.eclipse.jetty.websocket.core.internal.WebSocketCoreSession.closeConnection(WebSocketCoreSession.java:280)
        at org.eclipse.jetty.websocket.core.internal.WebSocketCoreSession.lambda$sendFrame$7(WebSocketCoreSession.java:514)
        at org.eclipse.jetty.util.Callback$3.succeeded(Callback.java:137)
        at org.eclipse.jetty.websocket.core.internal.TransformingFlusher.notifyCallbackSuccess(TransformingFlusher.java:151)
        at org.eclipse.jetty.websocket.core.internal.TransformingFlusher$Flusher.process(TransformingFlusher.java:111)
        at org.eclipse.jetty.util.IteratingCallback.processing(IteratingCallback.java:232)
        at org.eclipse.jetty.util.IteratingCallback.iterate(IteratingCallback.java:214)
        at org.eclipse.jetty.websocket.core.internal.TransformingFlusher.sendFrame(TransformingFlusher.java:75)
        at org.eclipse.jetty.websocket.core.internal.WebSocketCoreSession.sendFrame(WebSocketCoreSession.java:517)
        at org.eclipse.jetty.websocket.core.internal.WebSocketCoreSession.close(WebSocketCoreSession.java:236)
        at org.eclipse.jetty.websocket.core.internal.WebSocketCoreSession.processHandlerError(WebSocketCoreSession.java:367)
        at org.eclipse.jetty.websocket.core.internal.WebSocketCoreSession.lambda$onOpen$5(WebSocketCoreSession.java:401)
        at org.eclipse.jetty.util.Callback$3.failed(Callback.java:143)
        at org.eclipse.jetty.websocket.common.JettyWebSocketFrameHandler.onOpen(JettyWebSocketFrameHandler.java:187)
        at org.eclipse.jetty.websocket.core.internal.WebSocketCoreSession.lambda$onOpen$6(WebSocketCoreSession.java:407)
        at org.eclipse.jetty.server.handler.ContextHandler.handle(ContextHandler.java:1463)
        at org.eclipse.jetty.server.handler.ContextHandler.handle(ContextHandler.java:1482)
        at org.eclipse.jetty.websocket.core.server.internal.AbstractHandshaker$1.handle(AbstractHandshaker.java:212)
        at org.eclipse.jetty.websocket.core.internal.WebSocketCoreSession.onOpen(WebSocketCoreSession.java:407)
        at org.eclipse.jetty.websocket.core.internal.WebSocketConnection.onOpen(WebSocketConnection.java:545)
        at org.eclipse.jetty.io.AbstractEndPoint.upgrade(AbstractEndPoint.java:483)
        at org.eclipse.jetty.server.HttpConnection.upgrade(HttpConnection.java:419)
        at org.eclipse.jetty.server.HttpConnection.onCompleted(HttpConnection.java:450)
        at org.eclipse.jetty.server.HttpChannel.onCompleted(HttpChannel.java:884)
        at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:398)
        at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:282)
        at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:319)
        at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:100)
        at org.eclipse.jetty.io.SocketChannelEndPoint$1.run(SocketChannelEndPoint.java:101)
        at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:894)
        at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1038)
        at java.lang.Thread.run(Thread.java:833)
        at com.oracle.svm.core.thread.JavaThreads.threadStartRoutine(JavaThreads.java:596)
        at com.oracle.svm.core.posix.thread.PosixJavaThreads.pthreadStartRoutine(PosixJavaThreads.java:192)
Caused by: org.eclipse.jetty.websocket.core.exception.CloseException: org.eclipse.jetty.websocket.core.exception.WebSocketException: EventSocket OPEN method error: Invalid MethodHandle void([B, int, int) - expected void([B, int, int)
        ... 23 more
Caused by: org.eclipse.jetty.websocket.core.exception.WebSocketException: EventSocket OPEN method error: Invalid MethodHandle void([B, int, int) - expected void([B, int, int)
        ... 21 more
Caused by: org.eclipse.jetty.websocket.core.exception.InvalidSignatureException: Invalid MethodHandle void([B, int, int) - expected void([B, int, int)
        at org.eclipse.jetty.websocket.core.internal.messages.ByteArrayMessageSink.<init>(ByteArrayMessageSink.java:42)
        at java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:480)
        at com.oracle.svm.methodhandles.Util_java_lang_invoke_MethodHandle.invokeInternal(Target_java_lang_invoke_MethodHandle.java:210)
        at java.lang.invoke.MethodHandle.invokeBasic(MethodHandle.java:81)
        at java.lang.invoke.MethodHandle.invokeBasic(MethodHandle.java:0)
        at java.lang.invoke.LambdaForm$MH.0x00000007c1014000.invoke_MT(LambdaForm$MH)
        at org.eclipse.jetty.websocket.common.JettyWebSocketFrameHandlerFactory.createMessageSink(JettyWebSocketFrameHandlerFactory.java:212)
        at org.eclipse.jetty.websocket.common.JettyWebSocketFrameHandler.onOpen(JettyWebSocketFrameHandler.java:174)
        ... 20 more
Socket Closed: [1011] org.eclipse.jetty.websocket.core.exception.WebSocketException: EventSocket OPEN method error: Invalid MethodHandle void([B,

  • Here are my config files and log during native-image build:

native_library_info_20211114_213052.txt
target_info_20211114_213040.txt
jni-config.json.txt
predefined-classes-config.json.txt
proxy-config.json.txt
reflect-config.json.txt
resource-config.json.txt
serialization-config.json.txt

I think this issue is related to MethodHandle on GraalVM/Native-Image but I have no idea on how to fix it or if there is a workaround I can use.
Thank you for your help.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions