【问题标题】:ClassCastException: datastructures.instances.JClass cannot be cast to java.util.ArrayListClassCastException:datastructures.instances.JClass 不能转换为 java.util.ArrayList
【发布时间】:2015-06-08 22:55:51
【问题描述】:

我知道有很多关于 SO 的 CCE 问题。我已经详细或简要地阅读了其中的大部分内容,但我找不到任何适用于我的情况的内容。我的确切错误是:

Exception in thread "pool-1-thread-1" java.lang.ClassCastException: datastructures.instances.JClass cannot be cast to java.util.ArrayListif ((results = mCallsDownstreamCache.get(origin)) == null) {

正如您将在代码中看到的,我正在做的是从缓存 (HashMap) 中请求 ArrayList,然后对此做出决定。这里的奇怪行为是datastructures.instances.JClass 在生成错误的代码段中不可能引用。

为了给你一些背景信息,我有一个数据库“模型”,它满足来自“控制器”的请求。这些结果存储在模型本地的缓存中,如果它们存在,模型将返回缓存,因此不必访问数据库。我的缓存元素实际上是 Commons' JCS 的装饰器。

违规行包含在 block commentinline comment

public class AnalyzeModel extends Model {

    public final String TAG = getClass().getSimpleName();
    public CacheDecorator<Integer, JClass> mClassCache = new CacheDecorator<Integer, JClass>();
    public CacheDecorator<Integer, JMethod> mMethodCache = new CacheDecorator<Integer, JMethod>();
    public CacheDecorator<Integer, ArrayList<Integer>> mCallsUpstreamCache =
            new CacheDecorator<Integer, ArrayList<Integer>>();
    public CacheDecorator<Integer, ArrayList<Integer>> mCallsDownstreamCache =
            new CacheDecorator<Integer, ArrayList<Integer>>();

    public void close() {
        super.close();
    }

    public Pair<Integer, ArrayList<Integer>> selectCallGraphDownstream(int origin) {
        ArrayList<Integer> results = new ArrayList<Integer>();

        /**
         * This is the offending line
         */
        if ((results = mCallsDownstreamCache.get(origin)) == null) {
        // End error line
            results = new ArrayList<Integer>();
            for (Record r : mQuery.select(
                    mQuery.mQuerier.select(Calls.CALLS.TID)
                            .from(Calls.CALLS)
                            .where(Calls.CALLS.SID.eq(origin)))) {
                results.add(r.getValue(Calls.CALLS.TID));
            }
            mCallsDownstreamCache.put(origin, results);
            Statistics.CACHE_MISS++;
        } else {
            Statistics.CACHE_HITS++;
        }
        return new Pair<Integer, ArrayList<Integer>>(origin, results);
    }

}

public class CacheDecorator<K, V> {

    public final String TAG = getClass().getSimpleName();

    private CacheAccess<K, V> mCache;

    public CacheDecorator() {
        try {
            mCache = JCS.getInstance("default");
        } catch (CacheException e) {
            BillBoard.e(TAG, "Error getting cache configuration: " + e.toString());
            e.printStackTrace();
        }
    }

    /**
     * Get an object from cache
     * @param obj object to retrieve from cache
     * @return generic object of retrieved value, null if not found
     */
    public V get(K obj) {
        return mCache.get(obj);
    }

    /**
     * Place an object in cache
     * @param key generic key for reference
     * @param obj generic object to be cached
     */
    public synchronized void put(K key, V obj) {
        try {
            if(obj != null) {
                mCache.putSafe(key, obj);
            }
        } catch( CacheException e) {
            //BillBoard.d(TAG, obj.toString());
            //BillBoard.e(TAG, "Error placing item in cache: " + e.toString());
            //e.printStackTrace();
        }
    }

    /**
     * Get the stats from our cache manager
     * @return String of our cache object
     */
    public String getStats() {
        shutDownCache();
        return mCache.getStats();
    }

    public static void shutDownCache() {
        CompositeCacheManager.getInstance().shutDown();
    }
}

一些可能有用也可能没有帮助的额外细节:

  • Pair&lt;V, K&gt; 数据结构只是一个不可变的 2 对元组类
  • CacheDecorator.get(V obj) 如果缓存中不存在对象,则返回 null
  • 在选角等方面我已经尝试了很多
  • JClass 确实在代码的其他地方有引用,但在违规方法中没有引用
  • JClass 是一个 java 类的表示,它是一个自定义结构

【问题讨论】:

  • CachDecorator.get(int)的方法签名是什么?具体来说,该方法的返回类型是什么?
  • 我添加了CacheDecorator的类定义
  • 能否也添加JCS.getInstance 方法的实现?看起来您使用的是单例,但该默认实例是如何创建的,以及使用哪些数据类型?
  • 我不能,那是公共 JCS 的一部分。上面可能有一个 javadoc,但这是他们的代码。

标签: java class caching classcastexception jcs


【解决方案1】:

通过更改您的配置以包含documentation 中提供的特定于区域的配置,并将区域传递给您的包装器,应该可以解决问题。

看起来您为所有包装器使用相同的缓存区域,因此在包装器中引用相同的“底层缓存”。您能否将所有包装器的 mCache = JCS.getInstance("default"); 更改为 mCache = JCS.getInstance("uniqueNameForWrapper"); 之类的东西?

【讨论】:

  • 传递给实例的字符串严格用于解析 JCS 实例所需的属性配置。所以所有CacheAccess 实例都将使用配置的default 部分中定义的缓存策略。
  • 我在link line 162 上查看 JCS.getInstance 的源代码,沿着您最终到达 link line 591的路径>,我不熟悉 JCS,我可能是错的,但看起来该名称被用作底层 CacheAccess 对象的键
  • 嗯,这可能是答案的线索。我认为答案实际上可能在于使用defineRegiondefined。我的装饰器可能太简单了。我会做一些测试。从我读过的here 来看,JCS.getInstance([name]) 指的是定义缓存所需的属性文件。您可以看到我将他们的简单示例简单地装饰为通用接口。
  • 是的,我看到了那个,我怀疑每个区域定义都映射到一个“CacheAccess”对象。顺便说一句,您可以使用配置文件来定义自定义区域,如here
  • 顺便说一句,您可以定义自定义区域的另一种方式是使用像here 这样的配置文件。所以我看到它的方式;每个包装器都应该有自己对应的区域。不过有一个问题,你尝试过我的建议了吗?如果它仍然有效,我不会感到惊讶
猜你喜欢
  • 2020-12-20
  • 2023-03-29
  • 2013-07-11
  • 2018-02-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-03
  • 2013-03-24
相关资源
最近更新 更多