WebRTC 应用程序在 eclipse 中运行,但不在已编译的 jar 中

WebRTC application runs in eclipse, but not in a compiled jar

我构建了这个项目:https://github.com/Charles92011/WebRTCJavaTest
使用来自 java 的 WebRTC 库:https://github.com/devopvoid/webrtc-java
当我在eclipse中执行项目时,它运行良好,我可以建立连接。
但是,当我将它导出为可执行 jar 文件时,它会运行,但一旦我尝试连接,我就会收到异常:

java.lang.NoClassDefFoundError: Could not initialize class dev.onvoid.webrtc.PeerConnectionFactory

我 运行 windows 10,正在将 windows 本机库导入我的 jar 文件

有什么建议吗?

我正在使用 Eclipse 中的导出 Jar 文件功能构建它,并将所有必需的库打包到 jar 文件中。这是它创建的脚本:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project default="create_run_jar" name="Create Runnable Jar for Project WebRTCJavaTest">
    <!--this file was created by Eclipse Runnable JAR Export Wizard-->
    <!--ANT 1.7 is required                                        -->
    <!--define folder properties-->
    <property name="dir.buildfile" value="."/>
    <property name="dir.workspace" value="C:/Users/Charles Johnson/Documents/Workspaces/HelloWorld"/>
    <property name="dir.jarfile" value="${dir.buildfile}"/>
    <target name="create_run_jar">
        <jar destfile="${dir.jarfile}/javartc1.jar" filesetmanifest="mergewithoutmain">
            <manifest>
                <attribute name="Main-Class" value="main.Main"/>
                <attribute name="Class-Path" value="."/>
            </manifest>
            <fileset dir="C:/Users/Charles Johnson/Documents/GitLab/WebRTCJavaTest/target/classes"/>
            <zipfileset excludes="META-INF/*.SF" src="C:/Users/Charles Johnson/.m2/repository/org/glassfish/tyrus/tyrus-server/1.17/tyrus-server-1.17.jar"/>
            <zipfileset excludes="META-INF/*.SF" src="C:/Users/Charles Johnson/.m2/repository/org/glassfish/tyrus/tyrus-client/1.17/tyrus-client-1.17.jar"/>
            <zipfileset excludes="META-INF/*.SF" src="C:/Users/Charles Johnson/.m2/repository/org/glassfish/tyrus/tyrus-core/1.17/tyrus-core-1.17.jar"/>
            <zipfileset excludes="META-INF/*.SF" src="C:/Users/Charles Johnson/.m2/repository/org/glassfish/tyrus/tyrus-spi/1.17/tyrus-spi-1.17.jar"/>
            <zipfileset excludes="META-INF/*.SF" src="C:/Users/Charles Johnson/.m2/repository/jakarta/xml/bind/jakarta.xml.bind-api/2.3.2/jakarta.xml.bind-api-2.3.2.jar"/>
            <zipfileset excludes="META-INF/*.SF" src="C:/Users/Charles Johnson/.m2/repository/jakarta/activation/jakarta.activation-api/1.2.1/jakarta.activation-api-1.2.1.jar"/>
            <zipfileset excludes="META-INF/*.SF" src="C:/Users/Charles Johnson/.m2/repository/org/glassfish/tyrus/tyrus-container-grizzly-client/1.17/tyrus-container-grizzly-client-1.17.jar"/>
            <zipfileset excludes="META-INF/*.SF" src="C:/Users/Charles Johnson/.m2/repository/org/glassfish/tyrus/tyrus-container-grizzly-server/1.17/tyrus-container-grizzly-server-1.17.jar"/>
            <zipfileset excludes="META-INF/*.SF" src="C:/Users/Charles Johnson/.m2/repository/org/glassfish/grizzly/grizzly-framework/2.3.22/grizzly-framework-2.3.22.jar"/>
            <zipfileset excludes="META-INF/*.SF" src="C:/Users/Charles Johnson/.m2/repository/org/glassfish/grizzly/grizzly-http-server/2.3.22/grizzly-http-server-2.3.22.jar"/>
            <zipfileset excludes="META-INF/*.SF" src="C:/Users/Charles Johnson/.m2/repository/org/glassfish/grizzly/grizzly-http/2.3.22/grizzly-http-2.3.22.jar"/>
            <zipfileset excludes="META-INF/*.SF" src="C:/Users/Charles Johnson/.m2/repository/javax/websocket/javax.websocket-api/1.0/javax.websocket-api-1.0.jar"/>
            <zipfileset excludes="META-INF/*.SF" src="C:/Users/Charles Johnson/.m2/repository/dev/onvoid/webrtc/webrtc-java/0.3.0/webrtc-java-0.3.0.jar"/>
            <zipfileset excludes="META-INF/*.SF" src="C:/Users/Charles Johnson/.m2/repository/dev/onvoid/webrtc/webrtc-java/0.3.0/webrtc-java-0.3.0-windows-x86_64.jar"/>
            <zipfileset excludes="META-INF/*.SF" src="C:/Users/Charles Johnson/.m2/repository/com/googlecode/json-simple/json-simple/1.1/json-simple-1.1.jar"/>
        </jar>
    </target>
</project>

克隆你的存储库后,我花了 3 分钟才得到你的项目 运行ning。 MCVE 总是有帮助的。

只需添加 Maven Shade 插件:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-shade-plugin</artifactId>
  <version>3.3.0</version>
  <executions>
    <execution>
      <id>shade</id>
      <phase>package</phase>
      <goals>
        <goal>shade</goal>
      </goals>
      <configuration>
        <transformers>
          <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
            <mainClass>main.Main</mainClass>
          </transformer>
        </transformers>
      </configuration>
    </execution>
  </executions>
</plugin>

然后你会注意到:

$ mvn clean package
(...)

$ java -jar target/WebRTCJavaTest-0.0.1-SNAPSHOT.jar
Error: Unable to initialize main class main.Main
Caused by: java.lang.NoClassDefFoundError: javax/websocket/DeploymentException

通过 而不是 将网络套接字 API 的范围设置为 provided 来解决此问题,因为您需要在 JAR 中使用它:

<dependency>
  <groupId>javax.websocket</groupId>
  <artifactId>javax.websocket-api</artifactId>
  <version>1.0</version>
  <!--<scope>provided</scope>-->
</dependency>

重建,效果非常好。我尝试在我的 Windows 10 盒子上,在 Google Chrome 中打开两个浏览器选项卡,与我自己建立连接。当然,一个浏览器选项卡和镜像模式也可以。 DLL没有问题,找到并正常使用

我把剩下的留给你,即在创建 uber JAR 时消除由于重复的清单和许可证文件而导致的阴影警告。这可以在 Maven Shade 配置中使用 <filters> 来实现,如果您只是想删除不需要的文件,或者在适用的情况下使用转换器合并它们。否则,您可以忽略警告,以插件配置中转换器创建的清单为准。


更新: 这是我的 pull request 用于您的存储库。您可以简单地接受它来修复您的项目。


更新 2: 我以前在 IntelliJ 中工作,Maven 作为主要的构建工具。现在,我也打开了 Eclipse 2022-03 并从文件系统中导入了项目,但没有使用你的 Eclipse 项目设置。相反,我使用了 Maven 项目导入向导,所以我有了一个干净的开始,因为我知道从命令行或 IntelliJ IDEA 使用 Maven 时我的修复工作。所以我想在 Eclipse 中做同样的事情。

然后我使用了“文件”、“导出”、“可运行的 JAR 文件”。我选择了“将需要的库打包到生成的 JAR 中”和“另存为 ANT 脚本”。这是结果(我用你的用户名替换了我的用户名,所以你可以更容易地比较):

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project default="create_run_jar" name="Create Runnable Jar for Project SO_Java_WebRTCClassNotFound_71798010 with Jar-in-Jar Loader">
    <!--this file was created by Eclipse Runnable JAR file Export Wizard-->
    <!--ANT 1.7 is required-->
    <!--define folder properties-->
    <property name="dir.buildfile" value="."/>
    <property name="dir.workspace" value="${dir.buildfile}/.."/>
    <property name="dir.jarfile" value="${dir.buildfile}"/>
    <target name="create_run_jar">
        <jar destfile="${dir.jarfile}/MyExecutable.jar">
            <manifest>
                <attribute name="Main-Class" value="org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader"/>
                <attribute name="Rsrc-Main-Class" value="main.Main"/>
                <attribute name="Class-Path" value="."/>
                <attribute name="Rsrc-Class-Path" value="./ tyrus-server-1.17.jar tyrus-client-1.17.jar tyrus-core-1.17.jar tyrus-spi-1.17.jar jakarta.xml.bind-api-2.3.2.jar jakarta.activation-api-1.2.1.jar tyrus-container-grizzly-client-1.17.jar tyrus-container-grizzly-server-1.17.jar grizzly-framework-2.3.22.jar grizzly-http-server-2.3.22.jar grizzly-http-2.3.22.jar javax.websocket-api-1.0.jar webrtc-java-0.3.0.jar webrtc-java-0.3.0-windows-x86_64.jar json-simple-1.1.jar"/>
            </manifest>
            <zipfileset src="jar-in-jar-loader.zip"/>
            <fileset dir="${dir.jarfile}/target/classes"/>
            <zipfileset dir="C:/Users/Charles Johnson/.m2/repository/org/glassfish/tyrus/tyrus-server/1.17" includes="tyrus-server-1.17.jar"/>
            <zipfileset dir="C:/Users/Charles Johnson/.m2/repository/org/glassfish/tyrus/tyrus-client/1.17" includes="tyrus-client-1.17.jar"/>
            <zipfileset dir="C:/Users/Charles Johnson/.m2/repository/org/glassfish/tyrus/tyrus-core/1.17" includes="tyrus-core-1.17.jar"/>
            <zipfileset dir="C:/Users/Charles Johnson/.m2/repository/org/glassfish/tyrus/tyrus-spi/1.17" includes="tyrus-spi-1.17.jar"/>
            <zipfileset dir="C:/Users/Charles Johnson/.m2/repository/jakarta/xml/bind/jakarta.xml.bind-api/2.3.2" includes="jakarta.xml.bind-api-2.3.2.jar"/>
            <zipfileset dir="C:/Users/Charles Johnson/.m2/repository/jakarta/activation/jakarta.activation-api/1.2.1" includes="jakarta.activation-api-1.2.1.jar"/>
            <zipfileset dir="C:/Users/Charles Johnson/.m2/repository/org/glassfish/tyrus/tyrus-container-grizzly-client/1.17" includes="tyrus-container-grizzly-client-1.17.jar"/>
            <zipfileset dir="C:/Users/Charles Johnson/.m2/repository/org/glassfish/tyrus/tyrus-container-grizzly-server/1.17" includes="tyrus-container-grizzly-server-1.17.jar"/>
            <zipfileset dir="C:/Users/Charles Johnson/.m2/repository/org/glassfish/grizzly/grizzly-framework/2.3.22" includes="grizzly-framework-2.3.22.jar"/>
            <zipfileset dir="C:/Users/Charles Johnson/.m2/repository/org/glassfish/grizzly/grizzly-http-server/2.3.22" includes="grizzly-http-server-2.3.22.jar"/>
            <zipfileset dir="C:/Users/Charles Johnson/.m2/repository/org/glassfish/grizzly/grizzly-http/2.3.22" includes="grizzly-http-2.3.22.jar"/>
            <zipfileset dir="C:/Users/Charles Johnson/.m2/repository/javax/websocket/javax.websocket-api/1.0" includes="javax.websocket-api-1.0.jar"/>
            <zipfileset dir="C:/Users/Charles Johnson/.m2/repository/dev/onvoid/webrtc/webrtc-java/0.3.0" includes="webrtc-java-0.3.0.jar"/>
            <zipfileset dir="C:/Users/Charles Johnson/.m2/repository/dev/onvoid/webrtc/webrtc-java/0.3.0" includes="webrtc-java-0.3.0-windows-x86_64.jar"/>
            <zipfileset dir="C:/Users/Charles Johnson/.m2/repository/com/googlecode/json-simple/json-simple/1.1" includes="json-simple-1.1.jar"/>
        </jar>
    </target>
</project>

你看,这些库是完全一样的,我只创建了一个可执行 JAR,所以我还有一个带有 main class 的清单,以便能够 运行 带有 [= 的程序16=] 很容易。在我的变体中,有一个 jar-in-jar class 加载程序。 Maven Shade 的做法不同,将所有依赖项解包到目标 JAR 中,将它们混合在一起,而不是将 JAR 打包到超级 JAR 中。相反,Eclipse 的可执行 JAR 更类似于您在使用 Maven One Jar Plugin 时获得的 JAR。无论如何,两种方式都有效。我从 Eclipse 导出的生成的 JAR 完美运行,我可以连接到另一个会话或镜像我自己的相机。