[???] /
[Java FAQ] / [S171]
S171: 実行時エラー(スタックトレースの読み方)
[S171 Q-01]
実行時エラーの読み方は?
[S171 A-01]
実例で説明します。以下のソースコードを Test.java というファイル名で保存して、
コンパイル、実行してみてください。
public class Test {
public static void main(String[] args) {
String[] colorName = {"black", "blue", "green",
"red", "white", "yellow"};
System.out.println(colorName[6]);
}
}
以下のように実行時エラーがでると思います。
$ java Test
java.lang.ArrayIndexOutOfBoundsException: 6
at Test.main(Test.java:5)
これは配列において、宣言した範囲を越えた部分を参照したという意味のエラーです。
6 というのが、エラーを起こした配列の添字です。
そしてエラーが起こったのは、ソースコード Test.java の 5行目であることを
教えてくれているわけです。しかし、
java.lang.ArrayIndexOutOfBoundsException: 6
at Test.main(Compiled Code)
のように(Compiled Code)という表示のみで、場所を教えてくれない場合もあります。
JIT(JustInTime)コンパイラーつきで実行した場合です。この場合でも、
$ java -Djava.compiler=NONE Test
と JITなしで実行すればソースコードの何行目でエラーが起きたかわかります。
なお、長い実行時エラー(スタックトレース)の読みかたについては、
http://java-house.etl.go.jp/ml/archive/j-h-b/024782.html#body
が大変わかりやすいです。
参考記事 [JavaHouse-Brewers:3369]
[S171 Q-02]
java.lang.ArrayIndexOutOfBoundsException
[S171 A-02]
「配列(array)の添字(index)が範囲外(out of bounds)だぞ」という例外です。
配列は [10] として宣言すると要素は [0] から [9] までしか出来ません。
この時、[10] などの範囲外(out of bounds)の要素にアクセスすると起きる
例外です。
参考記事 [JavaHouse-Brewers:15816]
[S171 Q-03]
java.lang.NullPointerException
[S171 A-03]
null参照に対して、メソッドなどを呼んだ時に起こります。
このエラーメッセージがでたら、ソースコードのどこででているのかを
探すことが解決の早道です。System.out.println(); を各所に挿入して
null参照の変数を探してください。
場所がわかったら、次はなぜその変数が null のままなのかの原因を
探していくことになります。
NullPointerException がでる例を以下にのせます。
public class Test {
public static void main(String[] args) {
String string = null;
String value = string.valueOf(1); // static method OK.
int length = string.length(); // NullPointerException
}
}
string.length(); において、string は null のままですので、
NullPointerException が投げられることになります。
注意点として、staticメソッドは null参照に対しても呼べます。
上記例の string.valueOf() メソッドが staticメソッドです。
staticメソッドは、コンパイル時に変数の型情報から解決されるからです。
参考記事 [JavaHouse-Brewers:2668] [JavaHouse-Brewers:5602]
[JavaHouse-Brewers:8675]
[S171 Q-04]
Windows95/98で、実行時エラーをファイルにリダイレクトしたい
[S171 A-04]
Windows95/98 の MS-DOSプロンプトは標準エラー出力をリダイレクトできません。
bash、tcsh などのシェルをインストールするのが一つの解決方法です。
他には、自分で作成したプログラムであれば、
System.setErr(System.out);
をメインメソッドの最初に記述すれば、実行時エラーの内容が標準出力にでますので、
> 記号を用いて、ファイルにリダイレクトできるようになります。
商用 Javaアプリケーションのようにソースコードにアクセスできない場合には、
以下に示す InvokeMainMethod.java をコンパイルした後
$ java InvokeMainMethod 商用アプリケーション名 > エラー出力ファイル名
のような呼び出し方で、実行時エラーをファイルに出力できます。
import java.lang.reflect.*;
public class InvokeMainMethod {
public static void main(String[] args) throws Exception {
System.setErr(System.out);
Class cls = Class.forName(args[0]);
String[] args2 = new String[args.length - 1];
for (int i = 0; i < args2.length; i++) {
args2[i] = args[i + 1];
}
Method mainMethod = cls.getMethod("main", new Class[]{String[].class});
try {
mainMethod.invoke(null, new Object[]{args2});
} catch (InvocationTargetException e) {
e.getTargetException().printStackTrace();
}
}
}
参考記事 [JavaHouse-Brewers:23248] [JavaHouse-Brewers:23260]
[S171 Q-05]
アプレットで Javaコンソールに ClassFormatError
[S171 A-05]
クラスファイルが壊れているようです。
FTPで putする時に、ASCII mode でやると壊れることがあります。
FTPで binary などとうって BINARY mode で putしましょう。
一般に、ファイルがテキストファイルとして扱われると、
HTTP や FTP での転送の際に改行コードの変換や、
Mac の場合にはさらに「ISO 8859-1 <-> Mac独自コード」の変換が
なされてしまうようです。
あるいはクラスのロード中にコネクションが切れて不完全なクラス
ファイルを実行しようとした時にも起こるようです。
実行時エラーの例
# Applet exception: error: java.lang.ClassFormatError: Illegal constant pool type
java.lang.ClassFormatError: Illegal constant pool type
at java.lang.ClassLoader.defineClass(ClassLoader.java:250)
at netscape.applet.AppletClassLoader.loadClass(AppletClassLoader.java:620)
at netscape.applet.AppletClassLoader.findClass(AppletClassLoader.java:805)
at netscape.applet.AppletClassLoader.loadClass1(AppletClassLoader.java:688)
* at netscape.applet.AppletClassLoader.loadClass(AppletClassLoader.java:652)
at netscape.applet.AppletClassLoader.loadClass(AppletClassLoader.java:629)
at netscape.applet.DerivedAppletFrame$LoadAppletEvent.dispatch(DerivedAppletFrame.java:438)
at java.awt.EventDispatchThread$EventPump.dispatchEvents(EventDispatchThread.java:81)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:135)
at netscape.applet.DerivedAppletFrame$AppletEventDispatchThread.run(DerivedAppletFrame.java:911)
参考記事 [JavaHouse-Brewers:4955] [JavaHouse-Brewers:6971]
[JavaHouse-Brewers:7627] [JavaHouse-Brewers:18602]
[S171 Q-06]
Java.lang.ClassFormatError:Bad magic number
[S171 A-06]
原因は [S171-05] と同じでしょう。
参考記事 [JavaHouse-Brewers:12309]
[S171 Q-07]
java.io.IOException: bad zip file format
[S171 A-07]
jar などのアーカイブファイルが、壊れているようです。
原因は [S171-05] と同じでしょう。
参考記事 [JavaHouse-Brewers:23614]
[S171 Q-08]
Applet exception: error: java.lang.NoSuchMethodError: ...
[S171 A-08]
一般に、実行しようとしたメソッドがない場合に起こります。
Web Browser の Java VM(Virtial Machine) のバージョンが古いのが原因で、
Netscape Navigator 4.04 の頃に java.awt パッケージのメソッド関連で頻発
したエラーです。当時の解決法は、Navigator のバージョンを上げる(4.06)、
あるいは Java Plug-in を導入する、でした。
あとアプレットにて、引数をとるコンストラクターを宣言したことにより
引数を取らないコンストラクタ(デフォルトコンストラクタ)が存在しない
ことになり、上記エラーがでることがあります。ただしこの場合のメッセージは
JDK1.2 以降では java.lang.InstantiationException になるようです。
--- 追試用ソースコード ----
public class TestApplet extends java.applet.Applet {
public TestApplet(String[] args) {
}
}
---- 追試用 HTML ファイル ----
<applet code=TestApplet.class width=100 height=100>
</applet>
参考記事 [JavaHouse-Brewers:19273] [JavaHouse-Brewers:2760]
[S171 Q-09]
Applet exception: class ... got a security violation: method verification error
[S171 A-09]
Web Browser の Java VM(Virtial Machine) のバージョンが古いのが原因で、
Netscape Navigator 4.04 の頃に java.awt パッケージのメソッド関連で頻発
したエラーです。当時の解決法は、Navigator のバージョンを上げる(4.06)、
あるいは Java Plug-in を導入する、でした。
参考記事 [JavaHouse-Brewers:19273]
[S171 Q-10]
Applet exception: java.awt.Component: method ... not found
[S171 A-10]
原因は [S171-09] と同じでしょう。
[S171 Q-11]
java.net.MalformedURLException
[S171 A-11]
例えば、java.net.URL クラスのコンストラクタは、引数の文字列が正しい URL
の形をしていないときに、malformed な(出来損ないの) URL が指定されたよと、
この例外を発生させます。以下は、上記例外の発生する例です。
import java.net.URL;
public class Test {
public static void main(String[] args) throws Exception {
URL url = new URL("http;//hoge");
}
}
参考記事 [JavaHouse-Brewers:942]
[S171 Q-12]
java.io.UnsupportedEncodingException
[S171 A-12]
一般にコンバータの提供されていないエンコーディング名を指定した時に
起きるエラーです。エンコーディング名に間違いがないか確認ください。
Windows 環境用には U.S.English only な JRE(Java Runtime Environment) が
あって、この JRE で日本語をエンコーディングしようとすると起きるみたいです。
JDK 1.2 以降では、JDK-Install-Directory/jre/lib/i18n.jar に
エンコーディング用のクラスが含まれています。
参考記事 [JavaHouse-Brewers:13836]
[S171 Q-13]
Unable to initialize threads: cannot find class java/lang/Thread
[S171 A-13]
JDK/JRE のコアクラスが読めないようなクラスパス設定になっている時にでます。
JDK1.1.8 以前ではよく起こりましたが、JDK1.2 以降ではあまり起こりません。
JDK1.1.8 以前では JDK-Install-Directory/lib/classes.zip を明示的に含めない
ように、例えば以下のようにクラスパスを設定すると、上記エラーが出ます。
$ java -classpath . クラスファイル名
参考記事 [JavaHouse-Brewers:17719]
contributor: N.Amemiya
コメントの送り先 Java FAQ BBS