- PR -

java.lang.ArrayIndexOutOfBoundsExceptionがでます。

1
投稿者投稿内容
にきーた
会議室デビュー日: 2006/01/25
投稿数: 5
お住まい・勤務地: 東京都
投稿日時: 2006-02-13 19:11
ネットワークプログラミングの勉強をしていて、サーバーとクライアント間でファイルの転送をするプログラムを作ったのですが、java.lang.ArrayIndexOutOfBoundsExceptionがよく出ます。
しかし、動作には問題ないことがほとんどです。
普通のエラーだとソースファイルの何行目が悪いとエラーに書かれているのですが、このエラーにはUnknown Sourceとしかかかれていなくて原因がわかりません。
このようなソースファイルの原因箇所の書かれていないエラーはどういうときにおこるのでしょうか?

ご教授よろしくおねがいします。

Exception occurred during event dispatching:
java.lang.ArrayIndexOutOfBoundsException: 3 >= 3
at java.util.Vector.elementAt(Unknown Source)
at javax.swing.table.DefaultTableModel.getValueAt(Unknown Source)
at javax.swing.JTable.getValueAt(Unknown Source)
at javax.swing.JTable.prepareRenderer(Unknown Source)
at javax.swing.plaf.basic.BasicTableUI.paintCell(Unknown Source)
at javax.swing.plaf.basic.BasicTableUI.paintCells(Unknown Source)
at javax.swing.plaf.basic.BasicTableUI.paint(Unknown Source)
at javax.swing.plaf.ComponentUI.update(Unknown Source)
at javax.swing.JComponent.paintComponent(Unknown Source)
at javax.swing.JComponent.paint(Unknown Source)
at javax.swing.JComponent.paintWithOffscreenBuffer(Unknown Source)
at javax.swing.JComponent.paintDoubleBuffered(Unknown Source)
at javax.swing.JComponent._paintImmediately(Unknown Source)
at javax.swing.JComponent.paintImmediately(Unknown Source)
at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
at javax.swing.SystemEventQueueUtilities$ComponentWorkRequest.run(Unknown Source)
at java.awt.event.InvocationEvent.dispatch(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.Dialog$1.run(Unknown Source)
at java.awt.event.InvocationEvent.dispatch(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.Dialog$1.run(Unknown Source)
at java.awt.event.InvocationEvent.dispatch(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)
かつのり
ぬし
会議室デビュー日: 2004/03/18
投稿数: 2015
お住まい・勤務地: 札幌
投稿日時: 2006-02-13 19:30
javacで-g:noneのオプションを付加してコンパイルすると、
行番号・ソースファイル名・ローカル変数名の情報を
バイトコード内に含まないようにコンパイルができます。

Eclipseで作っているのであれば、
使用するランタイムがJREになっていませんか。
(Program Files/java/にあるやつです。)

JDKのランタイムを指定すると、デバッグ情報が含まれるようになります。
さらに、%JAVA_HOME%/src.zipをソースとして添付すると、
スタックトレースから原因の場所を直接見ることができます。

にきーた
会議室デビュー日: 2006/01/25
投稿数: 5
お住まい・勤務地: 東京都
投稿日時: 2006-02-13 21:53
回答ありがとうございます。

かつのりさんがおっしゃるようにEclipseの使用するランタイムがJREになっていました。JDKに変更してみたところ、ソースコードの名前と行が出るようになりました。

ただ、これで出てくるVector.java:431とかってライブラリのソースコードですよね?
自分で書いたソースコードの悪い箇所はどうやったらわかるのでしょうか?
いつものエラーだと、自分で書いたソースコードの悪い箇所がでてくるんですが…。

一応出てきたエラー載せておきます。

java.lang.ArrayIndexOutOfBoundsException: 0 >= 0
at java.util.Vector.elementAt(Vector.java:431)
at javax.swing.table.DefaultTableModel.getValueAt(DefaultTableModel.java:617)
at javax.swing.JTable.getValueAt(JTable.java:1771)
at javax.swing.JTable.prepareRenderer(JTable.java:3724)
at javax.swing.plaf.basic.BasicTableUI.paintCell(BasicTableUI.java:1149)
at javax.swing.plaf.basic.BasicTableUI.paintCells(BasicTableUI.java:1051)
at javax.swing.plaf.basic.BasicTableUI.paint(BasicTableUI.java:974)
at javax.swing.plaf.ComponentUI.update(ComponentUI.java:142)
at javax.swing.JComponent.paintComponent(JComponent.java:541)
at javax.swing.JComponent.paint(JComponent.java:808)
at javax.swing.JComponent.paintWithOffscreenBuffer(JComponent.java:4787)
at javax.swing.JComponent.paintDoubleBuffered(JComponent.java:4740)
at javax.swing.JComponent._paintImmediately(JComponent.java:4685)
at javax.swing.JComponent.paintImmediately(JComponent.java:4488)
at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:410)
at javax.swing.SystemEventQueueUtilities$ComponentWorkRequest.run(SystemEventQueueUtilities.java:117)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:189)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:478)
at java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:151)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:145)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:137)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:100)
未記入
ぬし
会議室デビュー日: 2004/09/17
投稿数: 667
投稿日時: 2006-02-14 09:12
引用:
自分で書いたソースコードの悪い箇所はどうやったらわかるのでしょうか?


推測するしかないですね。main メソッドからのトレースが表示されないのは、この例外が異なるスレッド(UIスレッド)で発生しているからです。

JTable の描画を行うためにセルの値を取得しようとして例外が発生しているようなので、以下の点を確認してみては。

・TableModel を介さずに直接、Vector の要素を削除したりしていませんか?
・UIスレッド以外から JTable を変更していませんか?
にきーた
会議室デビュー日: 2006/01/25
投稿数: 5
お住まい・勤務地: 東京都
投稿日時: 2006-02-14 18:05
回答ありがとうございます。

引用:

main メソッドからのトレースが表示されないのは、この例外が異なるスレッド(UIスレッド)で発生しているからです。


勉強不足でよくわからないのですが、ソースコードでスレッドを使うようにしていなくても、GUIの部分はJavaVMが自動的にスレッドとして処理している、と解釈していいんでしょうか?

引用:

・TableModel を介さずに直接、Vector の要素を削除したりしていませんか?
・UIスレッド以外から JTable を変更していませんか?


TableModelを使って要素の変更をしています。
UIスレッド以外からJTableを変更する、ということは自分で書いたソースコードの中からJTableに変更をしていないか、ということでしょうか?
自分で書いたソースコードの中にはTableModelを使ってJTableを変更するメソッドがあります。

下記に怪しい部分のソースコードを載せておきます。

コード:
class Table1 {
	String column[] = {"ファイル名", "サイズ", "ダウンロード率", "ダウンロード速度", "時間"};
	UneditableTableModel model = new UneditableTableModel(column, 0);
	JTable table = new JTable(model);
	
	//ダウンロード中ファイルリストにセルを追加
	public synchronized void addCell(Object[] file) {
		String filename = (String) file[0];
		int rowCount = model.getRowCount();
		
		for(int i = 0; i < rowCount; i++) {
			//同じファイル名のファイルをダウンロード中であれば上書き(置き換える)
			if( model.getValueAt(i, 0).equals(filename) ) {
				model.removeRow(i);
				//100%なら削除
				if( file[2].equals("100 %") ) {
					return;
				}
				model.insertRow(i, file);
				return;
			}
		}
		model.addRow(file);
	}
	
	//ダウンロード中のファイルとファイル名が一致するかどうかチェック
	public synchronized boolean isSame(String filename) {
		int rowCount = model.getRowCount();
		for(int i = 0; i < rowCount; i++) {
			if( model.getValueAt(i, 0).equals(filename) ) {
				return true;
			}
		}
		return false;
	}
}

class UneditableTableModel extends DefaultTableModel {
	UneditableTableModel(String[] columnNames, int rowNum){
        super(columnNames, rowNum);
    }

	//編集不可にする。
	public boolean isCellEditable(int row, int column) {
		return false;
	}
}


サーバーからファイルをダウンロードすると、クライアントのダウンロード中ファイル一覧(JTable)にそのリストが表示され、ファイル名やサイズやダウンロード率がわかるようになっています。
上記の二つのメソッド以外はJTableやTableModelに関係していません。
ArrayIndexOfBounsExceptionは複数のファイルを連続で同時に多数ダウンロードしたときに、発生します。(少数だったり、時間をおいて同時に多数ダウンロードとかだと発生しません。)
しかし、動作には問題ないです。
また、サーバー側もこれとまったく同じメソッドを使ってアップロード中のファイル一覧を表示するようにしてありますが、サーバー側にはArrayIndexOfBounsExceptionが発生しません。

どこがいけないのでしょうか?
よろしくお願いします。
ぶさいくろう
ぬし
会議室デビュー日: 2005/11/22
投稿数: 1232
お住まい・勤務地: 川崎市(は俺も含めてロクな人間が住んでないよw)
投稿日時: 2006-02-14 18:26
>どこがいけないのでしょうか?

デバッグくらいしようよ。
未記入
ぬし
会議室デビュー日: 2004/09/17
投稿数: 667
投稿日時: 2006-02-14 19:19
引用:
UIスレッド以外からJTableを変更する、ということは自分で書いたソースコードの中からJTableに変更をしていないか、ということでしょうか?


いいえ。UIスレッドで呼び出されるなら自分で書いたソースコードから変更を行っても問題ありません。

UIスレッドでコードを走らせるための方法は大きく分けて 2つあります。ひとつは GUI ウィジェットの操作リスナーとしてコードを記述する方法です。たとえば JButton の addActionListener を使用して登録したリスナーの actionPerformed は UIスレッドから呼ばれます。

もうひとつは、明示的に UIスレッドに処理を投入する方法です。おそらく、今回はファイル受信完了かなにかが JTable 変更のトリガになっているために、UIスレッド以外から変更が行われているものと思います。

コード:
SwingUtilities.invokeLater(new Runnable() {
    public void run() {
        hoge.addCell(...);
    }
});


こうすれば、addCell の処理が UIスレッドで行われます。

引用:
ArrayIndexOfBounsExceptionは複数のファイルを連続で同時に多数ダウンロードしたときに、発生します。(少数だったり、時間をおいて同時に多数ダウンロードとかだと発生しません。)
しかし、動作には問題ないです。
また、サーバー側もこれとまったく同じメソッドを使ってアップロード中のファイル一覧を表示するようにしてありますが、サーバー側にはArrayIndexOfBounsExceptionが発生しません。


タイミングの問題だから、動くときは動くし、動かないときは動かない。それだけだのことだと思うけど。少数なら絶対にうまく動くというなら UIスレッドの問題じゃあないですね。間違ったこと言ってすいません。あとは好きになさってください。
にきーた
会議室デビュー日: 2006/01/25
投稿数: 5
お住まい・勤務地: 東京都
投稿日時: 2006-02-15 20:55
回答ありがとうございました。
自己解決できました。
1

スキルアップ/キャリアアップ(JOB@IT)