为什么我的 maven 构建在执行时找不到 Netty 的 EventLoopGroup class?
Why is my maven build not finding Netty's EventLoopGroup class when executing?
我按照Netty的文档写了我的代码,然后我执行:
mvn package
构建成功。然后我运行:
java -jar target/netty-listener-0.0.1-SNAPSHOT.jar
它提示我这个错误:
Exception in thread "main" java.lang.NoClassDefFoundError:
io/netty/channel/EventLoopGroup at
java.lang.Class.getDeclaredMethods0(Native Method) at
java.lang.Class.privateGetDeclaredMethods(Class.java:2701) at
java.lang.Class.privateGetMethodRecursive(Class.java:3048) at
java.lang.Class.getMethod0(Class.java:3018) at
java.lang.Class.getMethod(Class.java:1784) at
sun.launcher.LauncherHelper.validateMainClass(LauncherHelper.java:544)
at
sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:526)
Caused by: java.lang.ClassNotFoundException:
io.netty.channel.EventLoopGroup at
java.net.URLClassLoader.findClass(URLClassLoader.java:381) at
java.lang.ClassLoader.loadClass(ClassLoader.java:424) at
sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331) at
java.lang.ClassLoader.loadClass(ClassLoader.java:357) ... 7 more
据我了解,JRE 在执行时没有找到 Netty 的 EventLoopGroup Class。在 Eclipse 中,我看到了对 Maven 的依赖选项卡的 netty-all 依赖,并且 EventLoopGroup 就在那里。我试过多次更改 Netty 的版本,但都不行。
这是我的主要代码:
package paplistener;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
public class PAPServer
{
private int port;
public PAPServer(int port)
{
this.port = port;
}
public void run() throws Exception
{
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new CommandDecoder(),
new PAPServerHandler());
}
})
.option(ChannelOption.SO_BACKLOG, 128)
.childOption(ChannelOption.SO_KEEPALIVE, true);
ChannelFuture f = b.bind(port).sync();
f.channel().closeFuture().sync();
} finally {
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
}
public static void main(String[] args) throws Exception
{
int port = 8080;
if(args.length > 0)
{
port = Integer.parseInt(args[0]);
}
new PAPServer(port).run();
}
}
它几乎与 Netty 文档中的代码完全相同,但它在管道的开头添加了一个解码器。
这是我的 pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>neurony.listener</groupId>
<artifactId>netty-listener</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.53.Final</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.12.1.GA</version>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<manifest>
<mainClass>paplistener.PAPServer</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.5.1</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>
${project.build.directory}/dependency-jars/
</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
我该怎么做才能解决这个问题?
EDIT1:将 maven-shade-plugin 添加到 pom.xml 但(相同)问题仍然存在。
添加到 pom 的行:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<manifestEntries>
<Main-Class>paplistener.PAPServer</Main-Class>
<Build-Number>1</Build-Number>
</manifestEntries>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
EDIT2:将 artifactSet 添加到 pom.xml 但它不起作用
<artifactSet>
<includes>
<include>io.netty:*</include>
</includes>
</artifactSet>
我也试过了 * : *,正如 Yuri G. 所建议的那样。
EDIT3:unzip -l 的内容:
Archive: netty-listener-0.0.1-SNAPSHOT.jar Length Date Time
Name
0 10-29-2020 10:17 META-INF/
266 10-29-2020 10:17 META-INF/MANIFEST.MF
0 10-29-2020 10:17 paplistener/
2903 10-29-2020 10:17 paplistener/PAPCommandHandler.class
2554 10-29-2020 10:17 paplistener/PAPServer.class
2103 10-29-2020 10:17 paplistener/CommandDecoder.class
2834 10-29-2020 10:17 paplistener/PAPServerHandler.class
1319 10-29-2020 10:17 paplistener/PAPServer.class
0 10-29-2020 10:17 META-INF/maven/
0 10-29-2020 10:17 META-INF/maven/neurony.listener/
0 10-29-2020 10:17 META-INF/maven/neurony.listener/netty-listener/
3572 10-28-2020 12:29 META-INF/maven/neurony.listener/netty-listener/pom.xml
125 10-29-2020 10:17 META-INF/maven/neurony.listener/netty-listener/pom.properties
15676 13 files
似乎没有将 netty 复制到 jar 文件中。但我仍然不知道如何解决它。我将在此处 link 生成的 .classpath(我猜是 Eclipse 生成的):
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src/test/java" output="target/test-classes" including="**/*.java"/>
<classpathentry kind="src" path="src/test/resources" output="target/test-classes" excluding="**/*.java"/>
<classpathentry kind="src" path="src/main/java" including="**/*.java"/>
<classpathentry kind="src" path="src/main/resources" excluding="**/*.java"/>
<classpathentry kind="output" path="target/classes"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.launching.macosx.MacOSXType/Java SE 8 [1.8.0_121]"/>
<classpathentry kind="var" path="M2_REPO/io/netty/netty-all/4.1.30.Final/netty-all-4.1.30.Final.jar" sourcepath="M2_REPO/io/netty/netty-all/4.1.30.Final/netty-all-4.1.30.Final-sources.jar"/>
<classpathentry kind="var" path="M2_REPO/javassist/javassist/3.12.1.GA/javassist-3.12.1.GA.jar" sourcepath="M2_REPO/javassist/javassist/3.12.1.GA/javassist-3.12.1.GA-sources.jar"/>
</classpath>
您缺少类路径。 Eclipse 管理自己的类路径,这就是它在 Eclipse 中工作的原因。
创建可以由 java -jar
执行的 jar
文件的最简单方法是使用 maven-shade-plugin
。您可以查看 documentation 了解如何使用 maven-shade-plugin.
创建可执行 jar
更新:
您需要按照 here 所述配置要包含在阴影 jar 中的工件。例如,如果你想包括所有依赖包括传递,你可以这样做:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
<configuration>
<artifactSet>
<includes>
<include>*:*</include>
</includes>
</artifactSet>
<shadedArtifactAttached>false</shadedArtifactAttached>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<manifestEntries>
<Main-Class>paplistener.PAPServer</Main-Class>
<Build-Number>1</Build-Number>
</manifestEntries>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
您可以在文档页面中查看所有可用配置https://maven.apache.org/plugins/maven-shade-plugin/shade-mojo.html
plugin元素不应该在build->pluginManagement->plugins里面,而是在build->plugins里面。像这样
<project>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.mycompany.app.App</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</project>
我按照Netty的文档写了我的代码,然后我执行:
mvn package
构建成功。然后我运行:
java -jar target/netty-listener-0.0.1-SNAPSHOT.jar
它提示我这个错误:
Exception in thread "main" java.lang.NoClassDefFoundError: io/netty/channel/EventLoopGroup at java.lang.Class.getDeclaredMethods0(Native Method) at java.lang.Class.privateGetDeclaredMethods(Class.java:2701) at java.lang.Class.privateGetMethodRecursive(Class.java:3048) at java.lang.Class.getMethod0(Class.java:3018) at java.lang.Class.getMethod(Class.java:1784) at sun.launcher.LauncherHelper.validateMainClass(LauncherHelper.java:544) at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:526) Caused by: java.lang.ClassNotFoundException: io.netty.channel.EventLoopGroup at java.net.URLClassLoader.findClass(URLClassLoader.java:381) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ... 7 more
据我了解,JRE 在执行时没有找到 Netty 的 EventLoopGroup Class。在 Eclipse 中,我看到了对 Maven 的依赖选项卡的 netty-all 依赖,并且 EventLoopGroup 就在那里。我试过多次更改 Netty 的版本,但都不行。
这是我的主要代码:
package paplistener;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
public class PAPServer
{
private int port;
public PAPServer(int port)
{
this.port = port;
}
public void run() throws Exception
{
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new CommandDecoder(),
new PAPServerHandler());
}
})
.option(ChannelOption.SO_BACKLOG, 128)
.childOption(ChannelOption.SO_KEEPALIVE, true);
ChannelFuture f = b.bind(port).sync();
f.channel().closeFuture().sync();
} finally {
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
}
public static void main(String[] args) throws Exception
{
int port = 8080;
if(args.length > 0)
{
port = Integer.parseInt(args[0]);
}
new PAPServer(port).run();
}
}
它几乎与 Netty 文档中的代码完全相同,但它在管道的开头添加了一个解码器。
这是我的 pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>neurony.listener</groupId>
<artifactId>netty-listener</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.53.Final</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.12.1.GA</version>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<manifest>
<mainClass>paplistener.PAPServer</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.5.1</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>
${project.build.directory}/dependency-jars/
</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
我该怎么做才能解决这个问题?
EDIT1:将 maven-shade-plugin 添加到 pom.xml 但(相同)问题仍然存在。
添加到 pom 的行:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<manifestEntries>
<Main-Class>paplistener.PAPServer</Main-Class>
<Build-Number>1</Build-Number>
</manifestEntries>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
EDIT2:将 artifactSet 添加到 pom.xml 但它不起作用
<artifactSet>
<includes>
<include>io.netty:*</include>
</includes>
</artifactSet>
我也试过了 * : *,正如 Yuri G. 所建议的那样。
EDIT3:unzip -l 的内容:
Archive: netty-listener-0.0.1-SNAPSHOT.jar Length Date Time Name
0 10-29-2020 10:17 META-INF/ 266 10-29-2020 10:17 META-INF/MANIFEST.MF 0 10-29-2020 10:17 paplistener/ 2903 10-29-2020 10:17 paplistener/PAPCommandHandler.class 2554 10-29-2020 10:17 paplistener/PAPServer.class 2103 10-29-2020 10:17 paplistener/CommandDecoder.class 2834 10-29-2020 10:17 paplistener/PAPServerHandler.class 1319 10-29-2020 10:17 paplistener/PAPServer.class 0 10-29-2020 10:17 META-INF/maven/ 0 10-29-2020 10:17 META-INF/maven/neurony.listener/ 0 10-29-2020 10:17 META-INF/maven/neurony.listener/netty-listener/ 3572 10-28-2020 12:29 META-INF/maven/neurony.listener/netty-listener/pom.xml 125 10-29-2020 10:17 META-INF/maven/neurony.listener/netty-listener/pom.properties
15676 13 files
似乎没有将 netty 复制到 jar 文件中。但我仍然不知道如何解决它。我将在此处 link 生成的 .classpath(我猜是 Eclipse 生成的):
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src/test/java" output="target/test-classes" including="**/*.java"/>
<classpathentry kind="src" path="src/test/resources" output="target/test-classes" excluding="**/*.java"/>
<classpathentry kind="src" path="src/main/java" including="**/*.java"/>
<classpathentry kind="src" path="src/main/resources" excluding="**/*.java"/>
<classpathentry kind="output" path="target/classes"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.launching.macosx.MacOSXType/Java SE 8 [1.8.0_121]"/>
<classpathentry kind="var" path="M2_REPO/io/netty/netty-all/4.1.30.Final/netty-all-4.1.30.Final.jar" sourcepath="M2_REPO/io/netty/netty-all/4.1.30.Final/netty-all-4.1.30.Final-sources.jar"/>
<classpathentry kind="var" path="M2_REPO/javassist/javassist/3.12.1.GA/javassist-3.12.1.GA.jar" sourcepath="M2_REPO/javassist/javassist/3.12.1.GA/javassist-3.12.1.GA-sources.jar"/>
</classpath>
您缺少类路径。 Eclipse 管理自己的类路径,这就是它在 Eclipse 中工作的原因。
创建可以由 java -jar
执行的 jar
文件的最简单方法是使用 maven-shade-plugin
。您可以查看 documentation 了解如何使用 maven-shade-plugin.
更新: 您需要按照 here 所述配置要包含在阴影 jar 中的工件。例如,如果你想包括所有依赖包括传递,你可以这样做:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
<configuration>
<artifactSet>
<includes>
<include>*:*</include>
</includes>
</artifactSet>
<shadedArtifactAttached>false</shadedArtifactAttached>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<manifestEntries>
<Main-Class>paplistener.PAPServer</Main-Class>
<Build-Number>1</Build-Number>
</manifestEntries>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
您可以在文档页面中查看所有可用配置https://maven.apache.org/plugins/maven-shade-plugin/shade-mojo.html
plugin元素不应该在build->pluginManagement->plugins里面,而是在build->plugins里面。像这样
<project>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.mycompany.app.App</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</project>