2017-10-10 60 views
2

下面的代码(检索通过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 

回答

4

正如在先前的更一般的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建议的两个问题,这使得它更清洁。