しおしお

IntelliJ IDEAのことなんかを書いてます

Class.newInstance()は、宣言されていないチェック例外を送出できてしまう

Javaセキュアコーディングスタンダードを読んでいて、Class.newInstance()は使うべきではないことを知りました。
理由は、チェック例外を宣言なしに送出できてしまうからのようです。もちろん、チェック例外をthrows宣言なしに送出できるわけで、コンパイラでもチェックすることはできません。
気になってJavaDoc見てみたらちゃんと注意点として書かれてますね。ぶっちゃけ、何年もJava書いてきたけど知りませんでした・・・。
http://docs.oracle.com/javase/6/docs/api/java/lang/Class.html#newInstance()

簡単なコードを書いて、Class.newInstance()とConstructor.newInstanceで動作の違いを確認してみました。

Class.newInstance()


上のコードを実行すると、以下のスタックトレースが出力されます。
invokeは、throws宣言がないにもかかわらずIOExceptionが呼び出し元に送出されていることがわかります。

Exception in thread "main" java.io.IOException
	at NewInstanceInClass.<init>(NewInstanceInClass.java:7)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
	at java.lang.Class.newInstance0(Class.java:372)
	at java.lang.Class.newInstance(Class.java:325)
	at NewInstanceInClass.invoke(NewInstanceInClass.java:18)
	at NewInstanceInClass.main(NewInstanceInClass.java:11)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:601)
	at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)

Constructor.newInstance()


上のコードを実行すると、チェック例外のIOExceptionがInvocationTargetExceptionでラップされて送出されていることがわかります。
InvocationTargetExceptionは、チェック例外で必ずキャッチ(throws)しないといけないので、コンパイル時に安全にチェックできるわけです。

java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
	at NewInstanceInConstructor.invoke(NewInstanceInConstructor.java:20)
	at NewInstanceInConstructor.main(NewInstanceInConstructor.java:13)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:601)
	at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
Caused by: java.io.IOException
	at NewInstanceInConstructor.<init>(NewInstanceInConstructor.java:9)
	... 11 more


Javaセキュアコーディングスタンダード CERT/ Oracle版
Fred Long Dhruv Mohindra Robert C. Seacord Dean F. Sutherland David Svoboda
アスキー・メディアワークス
売り上げランキング: 364986