1

ここで何が起こっているのかを理解するのに助けが必要です。マップに要素を挿入しているときに「IndexOutOfBoundsException」が発生しています。スタック トレースは次のとおりです。

 java.lang.IndexOutOfBoundsException: Index: 192, Size: 192
        at java.util.ArrayList.RangeCheck(ArrayList.java:547)
        at java.util.ArrayList.get(ArrayList.java:322)
        at somepackage.SequentialMap.getKey(Unknown Source)
        at somepackage.SequentialIterator.next(Unknown Source)
        at java.util.HashMap.buildCache(HashMap.java:590)
        at java.util.HashMap.resize(HashMap.java:576)
        at java.util.HashMap.addEntry(HashMap.java:939)
        at java.util.HashMap.put(HashMap.java:477)
        at somepackage.SequentialMap.put(Unknown Source)
        at somepackage.BatchBurstingInfo.parseContents(Unknown Source)
        at somepackage.BatchBurstingInfo.parse(Unknown Source)
        at somepackager.BatchBurstingInfo.setFileContents(Unknown Source)
        at somepackage.BurstingListBean.setMembers(Unknown Source)

上記の SequentialMap は HashMap を拡張しています。
ここでは、200 を超えるオブジェクトのリストを挿入しようとしています。問題は、JDK 1.6 を使用する開発セットアップで実行すると正常に動作することですが、weblogic サーバーでは、同じ手順で常にこの例外が発生します。
また、デバッグ中に HashMap クラスに buildCache メソッドが見つかりませんでした。それは、weblogic JDK が実装の異なるバージョンであることを意味します。

ここにコードスニペットがあります

public class SequentialMap extends HashMap
{
    private ArrayList m_keys = new ArrayList();

    /**
     * Removes the mapping for this key from this map if present.
     *
     * @param  key key whose mapping is to be removed from the map.
     * @return previous value associated with specified key, or <tt>null</tt>
     *         if there was no mapping for key.  A <tt>null</tt> return can
     *         also indicate that the map previously associated <tt>null</tt>
     *         with the specified key.
     */
    public Object remove(Object key) 
    {
        synchronized(this)
        {
                if(m_keys != null)
            {
                int iSize = m_keys.size();
                ArrayList oNewArray = new ArrayList();
                for(int i = 0; i < iSize; i++)
                {
                        if(m_keys.get(i).equals(key) == false)
                    {
                            oNewArray.add(m_keys.get(i));
                    }
                }
                m_keys = oNewArray;
            }
            return super.remove(key);
        }
    }   

    /**
     * Returns a collection view of the values contained in this map.  The
     * collection is backed by the map, so changes to the map are reflected in
     * the collection, and vice-versa.  The collection supports element
     * removal, which removes the corresponding mapping from this map, via the
     * <tt>Iterator.remove</tt>, <tt>Collection.remove</tt>,
     * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt> operations.
     * It does not support the <tt>add</tt> or <tt>addAll</tt> operations.
     *
     * @return a collection view of the values contained in this map.
     */
    /*public Collection values() 
    {
    }*/
    /**
     * Returns a collection view of the mappings contained in this map.  Each
     * element in the returned collection is a <tt>Map.Entry</tt>.  The
     * collection is backed by the map, so changes to the map are reflected in
     * the collection, and vice-versa.  The collection supports element
     * removal, which removes the corresponding mapping from the map, via the
     * <tt>Iterator.remove</tt>, <tt>Collection.remove</tt>,
     * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt> operations.
     * It does not support the <tt>add</tt> or <tt>addAll</tt> operations.
     *
     * @return a collection view of the mappings contained in this map.
     * @see Map.Entry
     */
    public Set entrySet() 
    {
            return super.entrySet();
    }

    /**
     * Removes all mappings from this map.
     */
    public void clear() 
    {
            synchronized(this)
        {
            m_keys.clear();
            super.clear();
        }
    }

    /**
     * Associates the specified value with the specified key in this map.
     * If the map previously contained a mapping for this key, the old
     * value is replaced.
     *
     * @param key key with which the specified value is to be associated.
     * @param value value to be associated with the specified key.
     * @return previous value associated with specified key, or <tt>null</tt>
     *         if there was no mapping for key.  A <tt>null</tt> return can
     *         also indicate that the HashMap previously associated
     *         <tt>null</tt> with the specified key.
     */
    public Object put(Object key, Object value) 
    {
        int iExistingIndex = this.getKeyIndex(key);
        Object oldObj = super.put(key, value);
        if(iExistingIndex == -1)
        {
            m_keys.add(key);
        }
        else
        {
                m_keys.add(iExistingIndex, key);
        }

        return oldObj;
    }

    /**
     * Returns a set view of the keys contained in this map.  The set is
     * backed by the map, so changes to the map are reflected in the set, and
     * vice-versa.  The set supports element removal, which removes the
     * corresponding mapping from this map, via the <tt>Iterator.remove</tt>,
     * <tt>Set.remove</tt>, <tt>removeAll</tt>, <tt>retainAll</tt>, and
     * <tt>clear</tt> operations.  It does not support the <tt>add</tt> or
     * <tt>addAll</tt> operations.
     *
     * @return a set view of the keys contained in this map.
     */
    public Set keySet() 
    {
        Set oSet = super.keySet();
        final SequentialMap oThis = this;
        HashSet oNewSet = new HashSet(oSet){
            /**
             * Returns an iterator over the elements in this set.  The elements
             * are returned in no particular order.
             *
             * @return an Iterator over the elements in this set.
             * @see ConcurrentModificationException
             */
            public Iterator iterator() {
                return new SequentialIterator(oThis);
            }
        };

        return oNewSet;
    }

    protected int getKeyIndex(Object key)
    {
        int index = -1;

            if(m_keys != null)
        {
            int iSize = m_keys.size();
            for(int i = 0; i < iSize; i++)
            {
                if(m_keys.get(i).equals(key))
                {
                        index = i;
                        break;
                }
            }
        }

        return index;
    }

    Object getKey(int index)
    {
            return m_keys.get(index);
    }
}



class SequentialIterator implements Iterator
{
    private SequentialMap m_oMap = null;
    private int m_iCurrentIndex = 0;

        SequentialIterator(SequentialMap oMap)
    {
            this.m_oMap = oMap;
    }
    /**
     * Returns <tt>true</tt> if the iteration has more elements. (In other
     * words, returns <tt>true</tt> if <tt>next</tt> would return an element
     * rather than throwing an exception.)
     *
     * @return <tt>true</tt> if the iterator has more elements.
     */
    public boolean hasNext() {
            return (m_iCurrentIndex < m_oMap.size());
    }
    /**
     * Returns the next element in the iteration.
     *
     * @return the next element in the iteration.
     * @exception NoSuchElementException iteration has no more elements.
     */
    public Object next() {
        Object key = m_oMap.getKey(m_iCurrentIndex);
        m_iCurrentIndex++;
        return key;
    }
    /**
     *
     * Removes from the underlying collection the last element returned by the
     * iterator (optional operation).  This method can be called only once per
     * call to <tt>next</tt>.  The behavior of an iterator is unspecified if
     * the underlying collection is modified while the iteration is in
     * progress in any way other than by calling this method.
     *
     * @exception UnsupportedOperationException if the <tt>remove</tt>
     *        operation is not supported by this Iterator.

     * @exception IllegalStateException if the <tt>next</tt> method has not
     *        yet been called, or the <tt>remove</tt> method has already
     *        been called after the last call to the <tt>next</tt>
     *        method.
     */
    public void remove() {
            Object key = m_oMap.getKey(m_iCurrentIndex - 1);
        m_oMap.remove(key);
    }
}
4

1 に答える 1

1

あなたの Weblogic は古いバージョンの JRockit を使用していると思います。前回のバージョンのソース コードを確認したところ、この buildCache はもう使用されていません。

よくわかりませんが、これを置き換えると次のようになると思います。

public boolean hasNext() {
        return (m_iCurrentIndex < m_oMap.size());
}

この実装の場合:

public boolean hasNext() {
        return (m_iCurrentIndex < m_keys.size());
}

このエラーは発生しません。

またNoSuchElementException、次の要素がない場合はIndexOutOfBoundsException、現在の実装が現在行っているスローの代わりに、on next() メソッドをスローする必要があります。

このようなものを追加します

if (!hasNext()) {
    throw new NoSuchElementException();
}
于 2012-04-09T08:03:50.523 に答える