maven - 具有默认访问权限的类会导致 java 11 的 Spring Boot 项目在运行时出现 NoClassDefFound 错误

标签 maven spring-boot java-11

我有一个使用 Java 11 的 spring-boot 项目。项目依赖于 redis,因此我在 pom.xml 中包含了 spring-boot-starter-data-redis 依赖项。 spring-data-redis jar 有一个名为 JedisClientUtils 的类,它在类级别有一个默认的访问修饰符。

当我使用 mvn spring-boot:run 运行此项目时,我收到 JedisClientUtils 类的 NoClassDefFound 错误。 在调试问题时,我发现使用 Java 8 时同一项目可以成功运行。 我的pom.xml有插件如下:

<build>
        <finalName>${war.name}</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
            <source>11</source>
            <target>11</target>
        </configuration>
                <dependencies>
                    <dependency>
                        <!-- update compiler plugin dependency on ASM for Java 11 compatibility -->
                        <groupId>org.ow2.asm</groupId>
                        <artifactId>asm</artifactId>
                        <version>6.2</version>
                    </dependency>
                </dependencies>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

使用默认访问类构建 java 11 项目还需要什么吗 日志供引用:

java.lang.reflect.InvocationTargetException at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0 (Native Method) at jdk.internal.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62) at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke (Method.java:566) at org.springframework.boot.maven.AbstractRunMojo$LaunchRunner.run (AbstractRunMojo.java:558) at java.lang.Thread.run (Thread.java:834) Caused by: java.lang.NoClassDefFoundError: Could not initialize class org.springframework.data.redis.connection.jedis.JedisClientUtils at org.springframework.data.redis.connection.jedis.JedisConnection.isQueueing (JedisConnection.java:339)

spring-boot-data-redis 版本:2.1.1.RELEASE jedis.版本:2.9.0

最佳答案

我遇到了类似的问题,但您的问题中没有足够的细节来确保它是相同的。

但是,如果这有帮助,这就是我所拥有的:
ForkJoinPool 实现在 java 8 之后的某个地方发生了更改,它可能会影响您的某些代码。一般来说,当 Java 中创建一个新线程时,它要么在构造函数中获取特定的类加载器,要么重用父级的类加载器。 Java 8 版本的 ForkJoinPool 没有为其线程指定类加载器(即使用父级线程),但 Java 11 的 ForkJoinPool 指定了系统类加载器。现在,当您尝试在 ForkJoinPool 线程中的某个位置按名称加载类而未指定正确的类加载器(如 JedisClientUtils 那样)时,默认情况下它将使用系统类加载器,而系统类加载器不知道您的应用程序类。 CompletableFuture 和并行 Streams 使用 ForkJoinPool 因此是此问题的潜在问题。 这是一个失败的示例:

@Repository
public interface RedisRepo extends CrudRepository<Statistic, Long> {
}

@SpringBootApplication
public class Start {
    ...
    public static void main(String[] args) {
        new SpringApplication(Start.class).run(args);
        CompletableFuture.runAsync(() -> {
            redisRepo.deleteAll();
        });
    }
}

可能的修复:

public static void main(String[] args) {
    new SpringApplication(Start.class).run(args);
    CompletableFuture.runAsync(() -> {
        ClassLoader contextClassLoaderBackup = Thread.currentThread().getContextClassLoader();
        try {
            Thread.currentThread().setContextClassLoader(Start.class.getClassLoader());
            redisRepo.deleteAll();
        } finally {
            Thread.currentThread().setContextClassLoader(contextClassLoaderBackup);
        }
    });
}

关于maven - 具有默认访问权限的类会导致 java 11 的 Spring Boot 项目在运行时出现 NoClassDefFound 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56967408/

相关文章:

maven - 为什么当我“mvn软件包”时某些目标运行两次?

maven - 在 IntelliJ IDEA 中导入 Maven 项目

javascript - Thymeleaf - 基于配置文件的 Spring Boot MVC 资源定位

spring-boot - JBAS015852 : Could not index class module-info. 类 - Spring Boot + Jboss 7.1.1

当位于两个目录之一时,Gradle 无法解析 java 11 模块的包

maven - 对于 Selenium WebDriver - Maven 和初始 pom.xml 配置

maven - 无法在 Glassfish 上运行 Arquillian 测试用例

spring - 如何在 Spring Boot 中根据配置文件运行/关闭选择性测试

java - Spring 版本 4.3.20 是否适用于 Java 11?

JavaFX 模块 javafx.graphics