的Java 9 Webstart的JNLP服务产生IllegalAccess
问题描述:
下面的代码(检索通过JNLP API一个Java Web Start的客户端应用程序的基本URL)中的Java 8工作,但失败时(模块化)的Java 9运行时执行:的Java 9 Webstart的JNLP服务产生IllegalAccess
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问题讨论是第二反射方法不受公共API类,但私有实现,这是自爪哇9无障碍环境不起作用定义规则适用。
修复方法是立足getCodeBase方法对公共接口代替:
Class<?> sclass = Class.forName("javax.jnlp.BasicService");
这也避免了反射反模式与动态定义类的工作。
使用静态实现也可以避免这个问题(但是这有一个问题,即它需要在某些构建环境中可能不容易获得的javaws.jar
)。
import javax.jnlp.BasicService;
import javax.jnlp.ServiceManager;
BasicService basicSvc = (BasicService)ServiceManager.lookup("javax.jnlp.BasicService");
URL u = basicSvc.getCodeBase();
由于@Holger检查猜测中的实际问题是什么,没有看到代码中的反射实现和@Alan Bateman。分开@nicolai建议的两个问题,这使得它更清洁。