考虑一个Web Start应用程序,它将一些jar放在一个目录中,然后执行其中一个。想想一个启动器/包装器。
为实现这一目标,我创建了一个指向jar的子URL类加载器,加载一个类并告诉它运行它的main()
。在其中创建JFrame
EXIT_ON_CLOSE
默认关闭操作。
类加载器的执行方式如下:
URLClassLoader cl = new URLClassLoader(
new URL[] { new File(tgtPath + "/inner.jar").toURI().toURL() },
Launcher.class.getClassLoader());
Class main = cl.loadClass("inner.Main");
main.getMethod("main", String[].class).invoke(
null,
new Object[] { new String[] { "My arg" } });
不幸的是,它会产生以下异常:
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at outer.Launcher.main(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.sun.javaws.Launcher.executeApplication(Launcher.java:1804)
at com.sun.javaws.Launcher.executeMainClass(Launcher.java:1750)
at com.sun.javaws.Launcher.doLaunchApp(Launcher.java:1512)
at com.sun.javaws.Launcher.run(Launcher.java:130)
at java.lang.Thread.run(Thread.java:662)
Caused by: java.security.AccessControlException: access denied (java.lang.RuntimePermission exitVM.0)
at java.security.AccessControlContext.checkPermission(AccessControlContext.java:374)
at java.security.AccessController.checkPermission(AccessController.java:546)
at java.lang.SecurityManager.checkPermission(SecurityManager.java:532)
at java.lang.SecurityManager.checkExit(SecurityManager.java:744)
at javax.swing.JFrame.setDefaultCloseOperation(JFrame.java:372)
at inner.Main.main(Unknown Source)
... 14 more
我认为原因是不允许子类加载器退出VM。如何禁用或绕过此限制?
编辑 - 回复评论:我真的希望内部流程能够调用System.exit
,而不是将应用和启动器连接在一起。
JNLP的安全设置:
<security>
<all-permissions/>
</security>