使用 Spring 框架的 WebSocketClient 时如何修复 NoClassDefFoundError
How can I fix NoClassDefFoundError when using Spring framework's WebSocketClient
我正在编写桌面 Java 应用程序作为 Web 服务客户端。我想使用 WebSocket 从服务器实现通知 "callback"。
我正在使用 Spring 框架的 WebSocketStompClient。下面的片段显示了我是如何初始化它的:
import org.springframework.web.socket.messaging.WebSocketStompClient;
import org.springframework.web.socket.sockjs.client.SockJsClient;
import org.springframework.web.socket.sockjs.client.Transport;
import org.springframework.web.socket.sockjs.client.WebSocketTransport;
...
List<Transport> transports = new ArrayList<>();
transports.add(new WebSocketTransport(new StandardWebSocketClient()));
stompClient = new WebSocketStompClient(new SockJsClient(transports));
...
如果我在 IntelliJ IDE 中 运行 它工作完美,但是,如果我通过命令行 运行 "java -cp my.jar MyPackage.MyMainClass",它将失败并显示以下消息:
Error: Unable to initialize main class MyMainClass
Caused by: java.lang.NoClassDefFoundError: org/springframework/web/socket/client/WebSocketClient
以上内容由 Java SE 12.0.2 生成。如果我 运行 它使用 Java SE 1.8,错误消息将是:
Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.NoClassDefFoundError:
org/springframework/web/socket/client/WebSocketClient
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Unknown Source)
at java.lang.Class.privateGetMethodRecursive(Unknown Source)
at java.lang.Class.getMethod0(Unknown Source)
at java.lang.Class.getMethod(Unknown Source)
at sun.launcher.LauncherHelper.validateMainClass(Unknown Source)
at sun.launcher.LauncherHelper.checkAndLoadMain(Unknown Source)
java.lang.NoClassDefFoundError
和 getDeclaredMethods0(Native Method)
都表明缺少本机模块(DLL)。
下面是我的 Gradle 脚本:
dependencies {
implementation project(':logman-common')
implementation 'org.springframework:spring-web:5.2.2.RELEASE'
implementation 'org.springframework:spring-websocket:5.2.2.RELEASE'
implementation 'org.springframework:spring-messaging:5.2.2.RELEASE'
... // other unrelated dependencies, such as GUI
}
我不认为这是因为缺少一些 JAR。我试过了:
- 添加
tyrus-standalone-client
到依赖列表,或者
- 使用
StandardWebSocketClient
代替SockJsClient
,
但错误依旧。
我想我的 OS (Win10) 中缺少一些本地库,但这无法解释为什么我可以 运行 它在 IntelliJ 中...
你能告诉我缺少什么吗?或者我该如何解决这个问题?谢谢!
尝试创建一个包含所有依赖项和 classes 的 fat jar。
将 build.gradle
脚本更新为如下所示:
apply plugin: 'java'
version = '...'
sourceCompatibility = 1.8
targetCompatibility = 1.8
// to create a fat jar.
jar {
manifest {
attributes "Main-Class": "MyPackage.MyMainClass"
}
from {
configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
}
}
dependencies {
implementation project(':logman-common')
implementation 'org.springframework:spring-web:5.2.2.RELEASE'
implementation 'org.springframework:spring-websocket:5.2.2.RELEASE'
implementation 'org.springframework:spring-messaging:5.2.2.RELEASE'
... // other unrelated dependencies, such as GUI
}
它将在根项目的 build/libs
中生成一个可执行的 fat jar,其中将包含所有项目文件(这包括所有依赖项、资源文件、.class 文件等上)。
注意: 对于旧版本的 Gradle,请使用此 configurations.compile.collect
而不是 configurations.runtimeClasspath.collect
。
你只需要用这个命令 运行 jar : java -jar <project-version>.jar
这应该可以解决您的问题。
错误消息显示 a JNI error has occurred
,因此这确实与本机程序集有关(您可以使用 LLDB 进行调试)。虽然我认为该库可能需要 Java EE 而不会在 Java SE 上 运行;可能与 Tyrus and other JSR 356 implementations. Either switch to another WebSocket implementation, which is known to work with desktop Java SE or write your own; the WebSocket HBYI protocol isn't that difficult; Java SE 11 even has a WebSocket.Builder.
相同
我正在编写桌面 Java 应用程序作为 Web 服务客户端。我想使用 WebSocket 从服务器实现通知 "callback"。
我正在使用 Spring 框架的 WebSocketStompClient。下面的片段显示了我是如何初始化它的:
import org.springframework.web.socket.messaging.WebSocketStompClient;
import org.springframework.web.socket.sockjs.client.SockJsClient;
import org.springframework.web.socket.sockjs.client.Transport;
import org.springframework.web.socket.sockjs.client.WebSocketTransport;
...
List<Transport> transports = new ArrayList<>();
transports.add(new WebSocketTransport(new StandardWebSocketClient()));
stompClient = new WebSocketStompClient(new SockJsClient(transports));
...
如果我在 IntelliJ IDE 中 运行 它工作完美,但是,如果我通过命令行 运行 "java -cp my.jar MyPackage.MyMainClass",它将失败并显示以下消息:
Error: Unable to initialize main class MyMainClass
Caused by: java.lang.NoClassDefFoundError: org/springframework/web/socket/client/WebSocketClient
以上内容由 Java SE 12.0.2 生成。如果我 运行 它使用 Java SE 1.8,错误消息将是:
Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.NoClassDefFoundError:
org/springframework/web/socket/client/WebSocketClient
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Unknown Source)
at java.lang.Class.privateGetMethodRecursive(Unknown Source)
at java.lang.Class.getMethod0(Unknown Source)
at java.lang.Class.getMethod(Unknown Source)
at sun.launcher.LauncherHelper.validateMainClass(Unknown Source)
at sun.launcher.LauncherHelper.checkAndLoadMain(Unknown Source)
java.lang.NoClassDefFoundError
和 getDeclaredMethods0(Native Method)
都表明缺少本机模块(DLL)。
下面是我的 Gradle 脚本:
dependencies {
implementation project(':logman-common')
implementation 'org.springframework:spring-web:5.2.2.RELEASE'
implementation 'org.springframework:spring-websocket:5.2.2.RELEASE'
implementation 'org.springframework:spring-messaging:5.2.2.RELEASE'
... // other unrelated dependencies, such as GUI
}
我不认为这是因为缺少一些 JAR。我试过了:
- 添加
tyrus-standalone-client
到依赖列表,或者 - 使用
StandardWebSocketClient
代替SockJsClient
,
但错误依旧。
我想我的 OS (Win10) 中缺少一些本地库,但这无法解释为什么我可以 运行 它在 IntelliJ 中...
你能告诉我缺少什么吗?或者我该如何解决这个问题?谢谢!
尝试创建一个包含所有依赖项和 classes 的 fat jar。
将 build.gradle
脚本更新为如下所示:
apply plugin: 'java'
version = '...'
sourceCompatibility = 1.8
targetCompatibility = 1.8
// to create a fat jar.
jar {
manifest {
attributes "Main-Class": "MyPackage.MyMainClass"
}
from {
configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
}
}
dependencies {
implementation project(':logman-common')
implementation 'org.springframework:spring-web:5.2.2.RELEASE'
implementation 'org.springframework:spring-websocket:5.2.2.RELEASE'
implementation 'org.springframework:spring-messaging:5.2.2.RELEASE'
... // other unrelated dependencies, such as GUI
}
它将在根项目的 build/libs
中生成一个可执行的 fat jar,其中将包含所有项目文件(这包括所有依赖项、资源文件、.class 文件等上)。
注意: 对于旧版本的 Gradle,请使用此 configurations.compile.collect
而不是 configurations.runtimeClasspath.collect
。
你只需要用这个命令 运行 jar : java -jar <project-version>.jar
这应该可以解决您的问题。
错误消息显示 a JNI error has occurred
,因此这确实与本机程序集有关(您可以使用 LLDB 进行调试)。虽然我认为该库可能需要 Java EE 而不会在 Java SE 上 运行;可能与 Tyrus and other JSR 356 implementations. Either switch to another WebSocket implementation, which is known to work with desktop Java SE or write your own; the WebSocket HBYI protocol isn't that difficult; Java SE 11 even has a WebSocket.Builder.