CacheBuilder中的NoSuchMethodError(checkState)

Ama*_*les 1 java caching java-ee guava

我创建了一个Guava(一个包含有用东西的库,在几乎任何Java项目中都非常方便,包括用于不可变集合的库,函数编程,I/O等等)基于CacheBuilder的缓存

 LoadingCache<String, Byte[]> companyDevicesCache = 
             CacheBuilder.newBuilder()
                .maximumSize(1000)                     // maximum 100 records can be cached
                .expireAfterAccess(24, TimeUnit.HOURS) // cache will expire after 30 minutes of access
                .build(new CacheLoader<String, Byte[]>(){ // build the cacheloader

                   @Override
                   public Byte[] load(String companyId) throws Exception {
                      //make the expensive call
                      return getFromServletContext (companyId);
                   }


                });
Run Code Online (Sandbox Code Playgroud)

我也试过了

CacheBuilder.newBuilder().expireAfterWrite(10, TimeUnit.MINUTES)
         .maximumSize(1000)
         .build(new CacheLoader<String, List<String>>() {
             @Override
             public List<String> load(String queryKey) throws Exception {
                 return null;
             }
         });
Run Code Online (Sandbox Code Playgroud)

并且

CacheLoader loader = new CacheLoader()
            {
                public String load(String key) throws Exception
                {
                    return null;
                }

                @Override
                public Object load(Object arg0) throws Exception {
                    // TODO Auto-generated method stub
                    return null;
                }
            };

         LoadingCache<String, String> persons = CacheBuilder.newBuilder() 
                 .initialCapacity(30) 
                 .maximumSize(40) 
                 .recordStats() 
                 .build(loader);
Run Code Online (Sandbox Code Playgroud)

final LoadingCache<String, Optional<Product>> cache =


               CacheBuilder.newBuilder()
                   .expireAfterWrite(1, TimeUnit.DAYS)
                   .refreshAfterWrite(1, TimeUnit.SECONDS)
                   .build( new CacheLoader<String, Optional<Product>>() {
                         @Override
                         public Optional<Product> load( String productId ) throws Exception {
                             return null;
                         }
                   }
             );
Run Code Online (Sandbox Code Playgroud)

但是当我初始化CacheBuilder时,我遇到了这个错误:

]] Root cause of ServletException.
java.lang.NoSuchMethodError: com.google.common.base.Preconditions.checkState(ZLjava/lang/String;J)V
        at com.google.common.cache.CacheBuilder.maximumSize(CacheBuilder.java:409)
Run Code Online (Sandbox Code Playgroud)

这是库的版本: guava-20.0-rc1.jar

这里的libs包含在耳中

在此输入图像描述

我也试图替换这个库,guava-19.0.jar但后来我得到了

]] Root cause of ServletException.
java.lang.IncompatibleClassChangeError: Found interface com.google.common.base.Equivalence, but class was expected
        at com.google.common.cache.LocalCache$Strength$1.defaultEquivalence(LocalCache.java:393)
        at com.google.common.cache.CacheBuilder.getKeyEquivalence(CacheBuilder.java:297)
        at com.google.common.cache.LocalCache.<init>(LocalCache.java:246)
        at com.google.common.cache.LocalCache$LocalLoadingCache.<init>(LocalCache.java:4868)
        at com.google.common.cache.CacheBuilder.build(CacheBuilder.java:786)
Run Code Online (Sandbox Code Playgroud)

Fra*_*eau 6

看起来你在com.google.common.base.Preconditions类路径上有这个类的多个版本(可能来自一个旧的google-collections jar?),或者是一个损坏的jar.

在Guava 20.0中添加了未找到的方法重载:

public static void checkState(boolean b, @Nullable String errorMessageTemplate, long p1)
Run Code Online (Sandbox Code Playgroud)

基于以下签名NoSuchMethodError:

checkState(ZLjava/lang/String;J)V
           ||                 | |
           ||                 | returns void
           ||                 |
           ||                 long
           |String
           |
           boolean
Run Code Online (Sandbox Code Playgroud)

通过在调用之前添加以下代码,您可以找到类定义的来源CacheBuilder.maximumSize():

System.out.println(com.google.common.base.Preconditions.class
        .getProtectionDomain()
        .getCodeSource()
        .getLocation()
        .toExternalForm());
Run Code Online (Sandbox Code Playgroud)

你会得到jar的URL.

我已经下载guava-20.0-rc1.jar从Maven的中央,提取其内容和检查的内容Preconditions.class使用javap,方法肯定是有:

$ javap Preconditions.class
Compiled from "Preconditions.java"
public final class com.google.common.base.Preconditions {
  // ...
  public static void checkState(boolean, java.lang.String, long);
  // ...
}
Run Code Online (Sandbox Code Playgroud)

在您的ant片段中,有多个通配符包含,例如:

<include name="**/spring/*.jar"/>
Run Code Online (Sandbox Code Playgroud)

可能会有一个额外版本的Guava,特别是考虑到切换到guava-19.0时出现的其他错误:Equivalence是一个接口,直到9.0,并在2011年更改为10.0 的.