英文:
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
但是它给我返回了这个错误:
> 异常线程 "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类。在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:
<!-- 在这里是你的pom.xml内容 -->
我应该如何解决这个问题?
编辑1:向pom.xml添加了maven-shade-plugin,但(相同的)问题仍然存在。
添加到pom的行:
<!-- 在这里是你向pom.xml添加的内容 -->
编辑2:向pom.xml添加了artifactSet,但没有起作用。
<!-- 在这里是你向pom.xml添加的内容 -->
我还尝试了 * : *,就像Yuri G.建议的一样。
编辑3:unzip -l的内容:
<!-- 在这里是unzip -l的内容 -->
看起来netty没有被复制到jar文件中。但我仍然不知道如何解决它。我会在这里链接生成的.classpath文件(我猜是Eclipse生成的):
<!-- 在这里是.classpath的内容 -->
这些是我翻译好的部分,关于具体的问题和解决方案,请查阅原文。
英文:
I wrote my code following Netty's documentation, then I execute:
mvn package
It builds successfully. Then I run:
java -jar target/netty-listener-0.0.1-SNAPSHOT.jar
And it promts me with this error:
> 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
To my understanding, the JRE is not finding Netty's EventLoopGroup Class in execution time. In Eclipse, I see the netty-all dependency on Maven's dependency tab and EventLoopGroup is there. I've tried to change Netty's version multiple times but it does not work.
Here is my main code:
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();
}
}
It is almost the exact code from Netty's documentation, but it adds a decoder in the beginning of the pipeline.
Here is my 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>
What can I do to solve this problem?
EDIT1: Added maven-shade-plugin to pom.xml but the (same) problem persists.
Lines added to 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: added artifactSet to pom.xml but it didn't work
<artifactSet>
<includes>
<include>io.netty:*</include>
</includes>
</artifactSet>
I tried * : * as well, just as Yuri G. suggested.
EDIT3: Contents of 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$1.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
It seems like netty is not being copied to the jar file. But I still don't know how to solve it. I'll link here the generated .classpath (I guess Eclipse generated it):
<?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>
答案1
得分: 1
你缺少了classpath。Eclipse 管理它自己的classpath,这就是为什么在Eclipse中可以工作。
创建一个可以通过 java -jar
直接执行的 jar
文件的最简单方法是使用 maven-shade-plugin
。你可以查看文档,了解如何使用 maven-shade-plugin
创建可执行的jar文件。
更新:
你需要配置要包含在shaded 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 找到所有可用的配置项。
英文:
You're missing the classpath. Eclipse manages its own classpath, that's why it works in Eclipse.
The easiest way to create a jar
file that can be executed simply by java -jar
is to use a maven-shade-plugin
. You can check the documentation for how to create an executable jar with maven-shade-plugin.
Update:
You need to configure which artifacts to include in the shaded jar as described here. For example if you want include all dependencies including transitive, you can do as following:
<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>
You can see all available configuration in the doc's page https://maven.apache.org/plugins/maven-shade-plugin/shade-mojo.html
答案2
得分: 1
<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>
英文:
The plugin element should not be inside build->pluginManagement->plugins, but inside build->plugins. Like this
<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>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论