You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

使用Google Guava缓存时遭遇com.google.common.cache.RemovalCause类未找到错误的排查咨询

排查Guava缓存RemovalCause类加载失败的问题

这问题我之前帮不少开发者排查过类似情况——虽然你已经确认guava-30.1-jre.jar里存在RemovalCause类,但NoClassDefFoundError很多时候不是Jar包缺失的问题,而是类加载器隔离依赖冲突这类更隐蔽的原因导致的。咱们一步步来拆解排查:

1. 优先排查依赖冲突(最常见原因)

很多时候项目里会间接引入旧版本的Guava,导致类加载时优先加载了旧版本的类(即便旧版本有RemovalCause,也可能因类加载器上下文不一致触发错误)。

  • 用依赖分析工具查看完整依赖树:
    • Maven项目执行:mvn dependency:tree | grep guava
    • Gradle项目执行:./gradlew dependencies | grep guava
  • 如果发现多个版本的Guava(比如18.x、20.x这类旧版本),需要在依赖管理里强制指定使用30.1-jre版本:
    • Maven中在<dependencyManagement>里锁定版本:
      <dependencyManagement>
          <dependencies>
              <dependency>
                  <groupId>com.google.guava</groupId>
                  <artifactId>guava</artifactId>
                  <version>30.1-jre</version>
              </dependency>
          </dependencies>
      </dependencyManagement>
      
    • Gradle中用force关键字强制版本:
      configurations.all {
          resolutionStrategy.force 'com.google.guava:guava:30.1-jre'
      }
      

2. 检查类加载器隔离问题

如果是Web应用(如Tomcat、Jetty)或模块化项目(Jigsaw模块),类加载器的隔离规则可能导致RemovalCauseLocalCache被不同加载器加载,从而触发错误。

  • 在报错代码附近添加调试代码,打印类加载器信息:
    // 打印LocalCache的类加载器
    System.out.println("LocalCache classloader: " + LocalCache.class.getClassLoader());
    try {
        // 尝试用LocalCache的类加载器加载RemovalCause
        Class<?> rcClass = Class.forName(
            "com.google.common.cache.RemovalCause", 
            true, 
            LocalCache.class.getClassLoader()
        );
        System.out.println("RemovalCause loaded with classloader: " + rcClass.getClassLoader());
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
    
  • 若两个类加载器不一致:
    • Web应用:检查容器lib目录是否存在Guava Jar,若有则删除,让应用优先使用WEB-INF/lib下的版本;
    • 模块化项目:确保module-info.java中正确引入Guava模块:
      module your.module.name {
          requires com.google.common;
      }
      

3. 排查字节码增强工具的干扰

如果项目使用了AspectJ、CGLIB、ByteBuddy这类字节码增强工具,或SkyWalking、Pinpoint这类监控工具,它们可能在修改Guava类的过程中破坏了RemovalCause的加载逻辑。

  • 临时禁用这些工具,重新部署应用,若问题消失,需调整工具配置,排除Guava的com.google.common.cache包不被增强。

4. 验证Jar包的实际可访问性

虽然你用jar -tf确认了类存在,仍可做个独立测试排除Jar包本身或环境权限问题:

  1. 写一个极简测试类:
    import com.google.common.cache.RemovalCause;
    
    public class GuavaTest {
        public static void main(String[] args) {
            System.out.println("Successfully loaded RemovalCause: " + RemovalCause.class);
            for (RemovalCause cause : RemovalCause.values()) {
                System.out.println("- " + cause);
            }
        }
    }
    
  2. 编译并运行:
    javac -cp guava-30.1-jre.jar GuavaTest.java
    java -cp .:guava-30.1-jre.jar GuavaTest
    

如果测试正常运行,说明Jar包本身没问题,问题出在你的应用环境中,回到前面的排查步骤即可。

5. 检查JVM类加载参数

查看应用启动时的JVM参数,确认是否设置了-Xbootclasspath-javaagent这类干扰类加载的参数——比如-Xbootclasspath包含旧版本Guava时,会优先加载系统类路径下的类,导致冲突。


内容的提问来源于stack exchange,提问作者Ravi Soni

火山引擎 最新活动