高速缓存中实现使用数组 - ArrayIndexOutOfBoundsException异常(JA

2019-10-19 10:16发布

我模拟Web缓存替换算法。 我可以为那些以串行方式到达缓存对象缓存和L型的请求的申请N个对象。

请求的对象可以通过INT字段REQID(从0数字ID多达N-1)来区分。 我不得不重写等于能够比较请求对象。

我实现了使用阵列的高速缓存 - 一种简单,朴素,静态数组。

缓存充满类型请求的对象,并具有最大尺寸M:

/** Max cache size */
private int M;

/** Cache */
private Request[] cache = new Request[M];

我有插入,驱逐和缓存中的对象的替代品。

我也曾经作为ArrayDeque实施的最后K请求的滑动窗口:

/** Max window size */
private int K;

/** Window */
private Deque<Request> window = new ArrayDeque<Request>(K);

值M和K在构造函数初始化,并在主要设置()。

我一直在一个HashMap对象的得分(在最后K请求的滑动窗口请求数):

/** Map of reqID (K) - Score (V) */
Map<Integer, Integer> score;

我守在缓存项的得分方面下令缓存,得分最高的是在左端和最低分是在右端。

由于这样的事实,当我有一个高速缓存命中一个项目的分数增加1分而当我有一个项目的请求从窗口该项目的分数减少1下降,在这种情况下,我可能有缓存有关项目在缓存中的下一个项目在其左侧或分别交换位置正确,重新排序。 所以,我应该能够知道在每个缓存(随机)项的指数在任何给定的时间。 为此,我使用所谓的反整型字段和一个HashMap叫的位置:

/** Counter = position in the cache */
private int counter;

/** Map of ReqID (K) - Counter (V) */
private Map<Integer, Integer> positions;

最后,我用一个inCache地图,以避免“for循环”,在查找操作:

/** Map with boolean flags to check whether an item (ReqID) is in cache or not */
private Map<Integer, Boolean> inCache;

和isMoreThanOne标志,以避免调用当前缓存大小,吸气时,这个尺寸较大:

/** Flag for more than 1 items in cache */
private boolean isMoreThanOne;

其原因是,由于我的高速缓存是香草阵列而不是一个ArrayList,它不具有一个大小()方法,和长度字段是给定的,而不是当前的高速缓存大小的固定容量。 因此,为了得到当前高速缓存大小,我应该做到以下几点(因为我不是100%,如果它是正确的,请看看):

/**
 * Getter for current cache size
 * @return  Current cache size
 */
public int getCacheSize() {

    // temp counter
int count = 0;

// scan the cache
for(int i = 0; i < this.cache.length; i++) {

    // as long as the items are not null
    if(this.cache[i] != null) {

        // increase the counter by 1
    count += 1;

    }

    // when the first null item found
    else {

        // jump out of the loop
    break;

    }

}

// return the current cache size (counter)
return count;
}

那长而neccessary介绍后,这里是缓存插入,我得到一个ArrayIndexOutOfBoundsException的代码:

/**
 * Cache insertion operation
 * @param request   The requested item that is inserted into the cache
 */
public void doCacheInsert(Request request) {

    // if this is the first item inserted into the cache
if(getCacheSize() == 0) {

    // set counter
    counter = M-1;

    // insert item at index counter
    this.cache[counter] = request;    // HERE I HAVE THE MESSAGE

    // put position index into positions list
    this.positions.put(request.reqID, counter);

}

// if this is not the first item inserted into the cache
else {

    //if the cache has not reached its max size
    if(getCacheSize() != this.cacheWindowLFU.length) {

        // decrease counter by 1
    counter -= 1;

    // insert item at index counter
    this.cache[counter] = request;

    // put position index into positions list
    this.positions.put(request.reqID, counter);

    // set isMoreThanOne flag
    isMoreThanOne = true;

    }

    // if the cache has reached its max size
    else {

        // reset counter to M-1
    counter = M-1;

    // insert item at index counter
    this.cache[counter] = request;

    }

}

// activate flag for item in inCache map
this.inCache.put(request.reqID, true);

}

我得到的消息几乎就在该方法的开始,在第1,如果在该行块:

// insert item at index counter
this.cache[counter] = request;

......我真的不知道为什么!

编辑:这是我的构造函数:

/**
 * Constructor
 * @param M Max cache size
 * @param K Max window size
 * @param N Number of items
*/
public Algorithm(int M, int K, int N) {

    // initialize max cache size and max window size
this.M = M;
this.K = K;

// initialize counter
counter = 0;

// initialize isMoreThanOne flag
isMoreThanOne = false;

// allocate inCache, winFreqs, and positions maps
inCache     = new HashMap<Integer, Boolean>(N);
scores          = new HashMap<Integer, Integer>(N);
positions   = new HashMap<Integer, Integer>(N);

}

这里是主要的相关部分(),这是主类中:

// stuff..... (e.g. # of sim runs etc.)

// number of items
int numItems = 20;

// number of requests
int numR = 40;

// maximum cache size
int M = 5;

// maximum window size
int K = 3;

// stuff...... (e.g. generation of requests, start of statistics etc.)

// instantianate object of type Algorithm
Algorithm alg = new Algorithm(M, K, numItems);

// stuff..... (e.g. lookup, insertion, replacement, # of hits, hit rate etc.)    

Answer 1:

以下变量初始化为0,由于实例变量初始化阶段。

/** Max cache size */
private int M; //set to 0 by default

/** Cache */
private Request[] cache = new Request[M]; //set to [] by default (an empty array)

移动cache初始化的构造,使高速缓存在创建初始化Algorithm实例:

/** Cache */
private Request[] cache;

public Algorithm(int M) { 
    this.M = M; 
    this.cache = new Request[M];  // set to Request[M]
}

这是Java 初始化块顺序是如下的结果:

  1. 静态实例变量(只运行一次,而第一类负载)
  2. 静态初始化块(只运行一次,而第一类负载)
  3. 超级构造函数(如果有的话)
  4. 实例变量(运行在每次创建新实例时间) --> M and cache set to 0
  5. 非静态初始化块(运行在每次创建新实例时)
  6. 构造--> M updated according to the parameter

根据上述规则,你可以看到, M最初默认为0值的M ,然后传送到cache ,其用0大小(空数组)分配从而导致ArrayIndexOutOfBoundsException异常(不管是什么值被分配到M构造函数中,已初始化cache为0的大小)。



Answer 2:

private int M;

是相同的

private int M = 0;

所以,如果你不分配它的任何值

    // set counter
    counter = M-1; //if M == 0, then counter = -1

    // insert item at index counter
    this.cache[counter] = request;    // if counter == -1, then you'll get an exception here

将返回到您的留言

java.lang.ArrayIndexOutOfBoundsException: -1

注意

private Request[] cache = new Request[M];

其中M == 0,仍然是一个有效的Java数组初始化,但你不能给它添加任何东西



文章来源: Cache Implemented Using an Array - ArrayIndexOutOfBoundsException (Java)