ポリシーファイルに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" とか必要になってくるかも。
