英文:
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>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论