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

2024-01-17

我有一个使用 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.InitationTargetException 在 jdk.internal.reflect.NativeMethodAccessorImpl.invoke0 (本机方法) 在 jdk.internal.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62) 在 jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43) 在 java.lang.reflect.Method.invoke (Method.java:566) 在 org.springframework.boot.maven.AbstractRunMojo$LaunchRunner.run (AbstractRunMojo.java:558) 在 java.lang.Thread.run (Thread.java:834) 引起:java.lang.NoClassDefFoundError: 无法初始化类 org.springframework.data.redis.connection.jedis.JedisClientUtils 在 org.springframework.data.redis.connection.jedis.JedisConnection.isQueueing (JedisConnection.java:339)

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


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

但是,如果这有帮助的话,这就是我所拥有的:
ForkJoinPooljava 8 之后的某个地方更改了实现,它可能会影响您的某些代码。一般来说,当 Java 中创建一个新线程时,它要么在构造函数中获取特定的类加载器,要么重用父级的类加载器。ForkJoinPoolJava 8 版本没有为其线程指定类加载器(即使用了父级的类加载器),但是ForkJoinPoolJava 11 指定系统类加载器。现在,当您尝试在线程中的某个位置按名称加载类时ForkJoinPool如果没有指定正确的类加载器(像 JedisClientUtils 那样),它将默认使用系统类加载器,它不知道您的应用程序类。CompletableFuture并平行Streams use 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);
        }
    });
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

随机推荐