Java 9 webstart JNLP服务产生IllegalAccess
Java 9 webstart JNLP Service produces IllegalAccess
以下代码(通过 JNLP API 检索 Java Web Start 客户端应用程序的基础 URL)在 Java 8 中有效但在执行时失败在(模块化)Java 9 运行时:
Class<?> mclass = Class.forName("javax.jnlp.ServiceManager");
Method lookup = mclass.getMethod("lookup", new Class[]{String.class});
Object basicSvc = lookup.invoke(null, new Object[{"javax.jnlp.BasicService"});
Class<?> sclass = basicSvc.getClass();
Method getCodeBase = sclass.getMethod("getCodeBase", (Class[])null);
URL codebase = (URL)getCodeBase.invoke(basicSvc, (Object[])null); // throws
结果
java.lang.IllegalAccessException: class app.App cannot access class
com.sun.jnlp.BasicServiceImpl (in module jdk.javaws) because module
jdk.javaws does not export com.sun.jnlp to unnamed module @7202a0fa
at java.base/jdk.internal.reflect.Reflection.newIllegalAccessException
at java.base/java.lang.reflect.AccessibleObject.checkAccess
at java.base/java.lang.reflect.Method.invoke
at app.App.init
如何解决这个问题?
正如前面讨论的更一般question问题是第二种反射方法不是由publicAPIclass定义的,而是私有实现,这不起作用,因为 Java 9 个可访问性规则适用。
解决方法是将 getCodeBase 方法改为基于 public 接口:
Class<?> sclass = Class.forName("javax.jnlp.BasicService");
这也避免了反射反模式与动态定义 classes 一起工作。
使用静态实现也可以避免这个问题(但是这有一个问题,它需要 javaws.jar
,这在某些构建环境中可能不容易获得)。
import javax.jnlp.BasicService;
import javax.jnlp.ServiceManager;
BasicService basicSvc = (BasicService)ServiceManager.lookup("javax.jnlp.BasicService");
URL u = basicSvc.getCodeBase();
感谢 @Holger to check the reflection implementation and @Alan Bateman in guessing what the actual problem was without seeing the code. Seperated the two questions as suggested by @nicolai,它变得更干净了。
以下代码(通过 JNLP API 检索 Java Web Start 客户端应用程序的基础 URL)在 Java 8 中有效但在执行时失败在(模块化)Java 9 运行时:
Class<?> mclass = Class.forName("javax.jnlp.ServiceManager");
Method lookup = mclass.getMethod("lookup", new Class[]{String.class});
Object basicSvc = lookup.invoke(null, new Object[{"javax.jnlp.BasicService"});
Class<?> sclass = basicSvc.getClass();
Method getCodeBase = sclass.getMethod("getCodeBase", (Class[])null);
URL codebase = (URL)getCodeBase.invoke(basicSvc, (Object[])null); // throws
结果
java.lang.IllegalAccessException: class app.App cannot access class
com.sun.jnlp.BasicServiceImpl (in module jdk.javaws) because module
jdk.javaws does not export com.sun.jnlp to unnamed module @7202a0fa
at java.base/jdk.internal.reflect.Reflection.newIllegalAccessException
at java.base/java.lang.reflect.AccessibleObject.checkAccess
at java.base/java.lang.reflect.Method.invoke
at app.App.init
如何解决这个问题?
正如前面讨论的更一般question问题是第二种反射方法不是由publicAPIclass定义的,而是私有实现,这不起作用,因为 Java 9 个可访问性规则适用。
解决方法是将 getCodeBase 方法改为基于 public 接口:
Class<?> sclass = Class.forName("javax.jnlp.BasicService");
这也避免了反射反模式与动态定义 classes 一起工作。
使用静态实现也可以避免这个问题(但是这有一个问题,它需要 javaws.jar
,这在某些构建环境中可能不容易获得)。
import javax.jnlp.BasicService;
import javax.jnlp.ServiceManager;
BasicService basicSvc = (BasicService)ServiceManager.lookup("javax.jnlp.BasicService");
URL u = basicSvc.getCodeBase();
感谢 @Holger to check the reflection implementation and @Alan Bateman in guessing what the actual problem was without seeing the code. Seperated the two questions as suggested by @nicolai,它变得更干净了。