为什么在作为 jar 运行时会得到 java.lang.ClassNotFoundException,但在 IntelliJ IDEA 中运行良好

时间:2020-12-25 09:53:41

标签: java spring-boot maven intellij-idea openfeign

春季启动版本:2.4.1

春云版本:2020.0.0

我的代码

for(int i = max_length - 1; i > index_num; i--) {
    arr[i] = arr[i - 1];
}

我的 pom.xml 依赖

@Configuration
public class BaseConfig {

    @Bean
    public Module sortJacksonModule() {
        return new SortJacksonModule();
    }
}

我的 pom.xml 插件

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-commons</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-openfeign-core</artifactId>
</dependency>

与 IntelliJ IDEA 一起运行时,效果很好。

但是当用 jar(by <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> ) 运行时,它显示

mvn clean package

在研究错误日志后,我发现Caused by: java.lang.NoClassDefFoundError: feign/codec/EncodeException at org.springframework.cloud.openfeign.support.SortJacksonModule.setupModule(SortJacksonModule.java:47) ~[spring-cloud-openfeign-core-3.0.0.jar!/:3.0.0] at com.fasterxml.jackson.databind.ObjectMapper.registerModule(ObjectMapper.java:819) ~[jackson-databind-2.11.3.jar!/:2.11.3] at com.fasterxml.jackson.databind.ObjectMapper.registerModules(ObjectMapper.java:1021) ~[jackson-databind-2.11.3.jar!/:2.11.3] at org.springframework.http.converter.json.Jackson2ObjectMapperBuilder.configure(Jackson2ObjectMapperBuilder.java:712) ~[spring-web-5.3.2.jar!/:5.3.2] at org.springframework.http.converter.json.Jackson2ObjectMapperBuilder.build(Jackson2ObjectMapperBuilder.java:680) ~[spring-web-5.3.2.jar!/:5.3.2] at org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$JacksonObjectMapperConfiguration.jacksonObjectMapper(JacksonAutoConfiguration.java:101) ~[spring-boot-autoconfigure-2.4.1.jar!/:2.4.1] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_232] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_232] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_232] at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_232] at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154) ~[spring-beans-5.3.2.jar!/:5.3.2] ... 113 common frames omitted Caused by: java.lang.ClassNotFoundException: feign.codec.EncodeException at java.net.URLClassLoader.findClass(URLClassLoader.java:382) ~[na:1.8.0_232] at java.lang.ClassLoader.loadClass(ClassLoader.java:418) ~[na:1.8.0_232] at org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:151) ~[demo-spring-core-11-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT] at java.lang.ClassLoader.loadClass(ClassLoader.java:351) ~[na:1.8.0_232] ... 124 common frames omitted feign.codec.EncodeException中的可选依赖项,因此ClassNotFoundException是正确的行为(可选依赖项不包含在最终jar中)。

所以我的问题是:为什么 IntelliJ IDEA 可以毫无错误地运行?我尝试了 IntelliJ IDEA run 和 mvn spring-boot:run,都很好。

更新:添加示例

经过更多研究,我发现只有在没有调用类时才会发生这种情况。

spring-cloud-openfeign-core

在这个例子中,try catch 从不​​抛出异常。并且 try { System.out.println("not important code"); } catch (Exception e) { throw new EncodeException("not exist class"); } 类处于可选依赖项中。 此代码在 IntelliJ IDEA 中运行良好,但作为 EncodeException

运行时失败

========== 用最少的演示再次更新

我创建了一个最小的演示来重现这个问题。

  • 一个独立的演示模块
java -jar xxx.jar
        <dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-core</artifactId>
            <version>10.10.1</version>
            <optional>true</optional>
        </dependency>
  • 演示 spring 项目(由 import feign.codec.EncodeException; /** * Hello world! */ public class App { public void testOptional() { try { System.out.println("test"); } catch (Exception e) { throw new EncodeException("never throw this"); } } } 创建并添加依赖项)
spring initializr
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>com.example</groupId>
            <artifactId>demo-module</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>

2 个答案:

答案 0 :(得分:0)

在 Idea ( CTRL-Alt-Shift-S ) 中检查您的项目类路径 - 我敢说可选 jar 位于模块编译类路径中的某个位置,它足以在 IDE 中运行您的类 - 但不能在独立 jar 中运行。可选意味着在 maven 上下文中,它在编译时出现在类路径中,但不会打包到生成的工件中。

答案 1 :(得分:0)

IntelliJ IDEA 运行配置中有一个名为 Enable launch optimization 的选项,取消选中它,一切都会按预期工作。