【Java】思わぬところでjava.lang.IndexOutOfBoundsException


springで開発をしていて思わぬところでIndexOutOfBoundsExceptionが発生し、そこそこハマったので
自分と同じように時間を無駄にする犠牲者が増えないように、と思い記事にしてみました。

経緯などざっくり

jsp側でformで飛ばす値を以下のように記述

...
<c:forEach items="${list}" var="value" varStatus="status">
	...
	<input type="hidden" name="updateList[${status.index}].id" value="${value.id}">
	...
</c:forEach>
...

そしてsubmitすると…

インデックスが有効じゃないよ!!と怒られたわけです。

配列(updateList[])まわりを確認するもおかしい点は見つけられず…

そもそもIndexOutOfBoundsExceptionって何?

こちらに解決・回避方法も含め書いてあります。

結論から言うと

インデックスの上限は決まっており超えると
java.lang.IndexOutOfBoundsException: Index: 256, Size: 256
となります。

上限値を記述しているところは、org.springframework.validation.DataBinderの中のDataBinder.classです。

	...
	/** Default limit for array and collection growing: 256 */
	public static final int DEFAULT_AUTO_GROW_COLLECTION_LIMIT = 256;
	...

配列とコレクションのデフォルトの制限は256にするよ、だそう。
制限を256なので、指定できるインデックスは0-255までになります。
なので256が指定されたとき上記のような表示がでていたのかとここでやっと理解&納得できました。

公式にも書いてありましたので英語ですが覗いてみてください。

解決方法

上限値を変更することで対処できます。

org.springframework.validation.DataBinderの中のDataBinder.class内にsetAutoGrowCollectionLimitというメソッドがあり
これを呼び出して設定します。
以下は制限を256→1000に変更する場合です。

	// インデックスの上限を引き上げる処理
	@InitBinder
	public void initBinder(WebDataBinder binder) {
		binder.setAutoGrowCollectionLimit(1000);
	}

解決するまで…長い道のりだった……orz

まとめ

・インデックスの上限は決まっている
・「java.lang.IndexOutOfBoundsException: Index: 256, Size: 256」がでたら、インデックスの上限のせい
・上限値を変更することで対処可能

思ったほど根が深くなくてすんなり解決できて良かったと思いつつも、結構時間かかってしまった…。
こんな仕様もあるので、頭の片隅に入れて開発を行いたいものです。良い教訓になりました。

  • このエントリーをはてなブックマークに追加

PAGE TOP