以下代码(通过JNLP API检索Java客户端应用程序的基本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怎么解决这个问题呢?
发布于 2017-10-10 14:13:18
正如前面更一般的question中所讨论的那样,问题是第二个反射方法不是由公共API类定义的,而是由私有实现定义的,这是因为Java9可访问性规则适用了。
修复方法是将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();感谢https://stackoverflow.com/users/2711488/holger检查反射实现和https://stackoverflow.com/users/7463126/alan-bateman,在没有看到代码的情况下猜测实际问题是什么。按照https://stackoverflow.com/users/2525313/nicolai的建议,将这两个问题分开,使其更加清晰。
https://stackoverflow.com/questions/46669000
复制相似问题