建立非公用介面的新實例時的行為變更

對於使用 Proxy.getProxyClassConstructor.newInstance 方法來建立 Proxy 實例的程式碼,如果呼叫端與非公用 Proxy 介面不在相同的執行時期套件中,Java 8 引進行為變更。 在 Java 7 中,使用這些方法會建立 Proxy 類別。在 Java 8 中,則會失敗並擲出 IllegalAccessException

因為分析器不一定都能判斷所使用的介面或其可見性,此規則會標示 Constructor.newInstance(InvocationHandler) 的所有呼叫,除非它定義為可存取。如果 Constructor.newInstance(InvocationHandler) 方法的呼叫位於呼叫了下列方法的相同方法前面,則此規則不會標示該方法的呼叫:

請檢查標示的程式碼,查明是否從其他執行時期套件中呼叫 getProxyClass 方法,以及是否有任何 Proxy 介面為非公用。例如,沒有 public 關鍵字的套件層次介面就是非公用。

如果要在 Java 8 中建立 Proxy 類別,請採用下列其中一項技術:

如果安全管理程式存在,則這兩個解決方案都需要有 ReflectPermission("newProxyInPackage.{package name}") 權限,才能避免 SecurityException

下列範例顯示您如何在 proxyClass 方法將非公用介面實例化時變更程式碼:

原始程式碼:
public Object instantiateClass(Class<?> proxyClass, InvocationHandler handler) throws Exception {

Object o=null;

o = proxyClass.getConstructor(InvocationHandler.class).newInstance(handler);
return o;
}

解決方案 1:
public Object instantiateClass(Class<?> proxyClass, InvocationHandler handler) throws Exception {

Object o=null;

o = proxyClass.getConstructor(InvocationHandler.class).newInstance(handler);
Constructor c = proxyClass.getConstructor(InvocationHandler.class);
c.setAccessible(true);
o = c.newInstance(handler);
return o;
}

解決方案 2:
public Object instantiateClass(Class<?> proxyClass, InvocationHandler handler) throws Exception {

Object o=null;
o = Proxy.newProxyInstance(proxyClass.getClassLoader(), proxyClass.getInterfaces(), handler);
return o;
}

如需相關資訊,請參閱下列類別的 Java 說明文件: