ポリシーファイルにexitVM権限を付加しなくても、アプリはSystem.exit()可能だそうです。ここを流し読みした感じ、sun.misc.Launcher.AppClassLoader経由ではexitVM権限が付加されるみたい。確かに、デフォルトのjava.policyにはexitVM権限は書かれていないのに、セキュリティマネージャを有効にしてもexit()は可能ですねえ。
ならば、URLClassLoader経由でロードさせればSystem.exit()できなくなるんでしょうか? Runnableを継承したOuterClassを作って、CLASSPATHの通ってないディレクトリに置いて試してみます。OuterClass.run()からSystem.exit()を呼んでます。
Runnable outerClass = null; try{ ClassLoader cl = new URLClassLoader( new URL[] {new File("CLASSPATHの通ってないディレクトリ").toURL()} ); Class cls = cl.loadClass("OuterClass"); outerClass = (Runnable) cls.newInstance(); }catch(Exception e){ throw new RuntimeException(e); } outerClass.run(); 【結果】 Exception in thread "main" java.security.AccessControlException: access denied (java.lang.RuntimePermission exitVM) at java.security.AccessControlContext.checkPermission(Unknown Source) at java.security.AccessController.checkPermission(Unknown Source) at java.lang.SecurityManager.checkPermission(Unknown Source) at java.lang.SecurityManager.checkExit(Unknown Source) at java.lang.Runtime.exit(Unknown Source) at java.lang.System.exit(Unknown Source) at OuterClass.run(OuterClass.java:12) at PolicyTest.main(PolicyTest.java:41)
出ました! おめでとう。
にしても、ClassLoaderを含めたjavaのセキュリティの話は難しいですね。書籍を買って勉強したほうがいいかなあ。たとえば↓とか。
Javaセキュリティ
スコット オークス Scott Oaks 島田 秋雄
ちなみに、この実験をするのにいくらか準備が必要です。まず、SecurityManagerを有効にするために、javaを-Djava.security.manager付きで起動する必要があります。
でもって、SecurityManagerが有効になるとClassLoaderの作成ができなくなったりする可能性があるので、自作のpolicyファイルを作ってjavaに与えます。-Djava.security.policy=ポリシファイルPATH、とオプションで指定するといいです。
grant { permission java.lang.RuntimePermission "createClassLoader"; //permission java.lang.RuntimePermission "exitVM"; };
他、実行する条件によっては java.util.PropertyPermission "user.dir", "read" とか java.io.FilePermission "hogedir${/}-", "read" とか必要になってくるかも。