Zmiana działania podczas tworzenia nowych instancji interfejsów niepublicznych

W środowisku Java 8 zmieniono działanie kodu korzystającego z metod Proxy.getProxyClass i Constructor.newInstance w celu utworzenia instancji proxy, jeśli program wywołujący nie znajduje się w tym samym pakiecie wykonawczym co niepubliczny interfejs proxy. W środowisku Java 7 użycie tych metod powoduje utworzenie klasy proxy. W środowisku Java 8 działanie to kończy się niepowodzeniem i zgłaszany jest wyjątek IllegalAccessException.

Ponieważ analizator nie zawsze może określić używane interfejsy lub ich widoczności, ta reguła powoduje oznaczenie wszystkich wywołań metody Constructor.newInstance (InvocationHandler) z wyjątkiem sytuacji, gdy są zdefiniowane jako dostępne. Reguła nie powoduje oznaczania wywołań metody Constructor.newInstance(InvocationHandler), które są poprzedzone w tej samej metodzie wywołaniami następujących metod:

Należy zbadać oznaczony kod, sprawdzając, czy metoda getProxyClass jest wywoływana z innych pakietów środowiska wykonawczego i czy dowolny z interfejsów proxy jest niepubliczny. Niepubliczny jest na przykład interfejs na poziomie pakietu, który nie ma słowa kluczowego public.

Aby utworzyć klasę proxy w środowisku Java 8, należy zastosować jedną z następujących technik:

Jeśli obecny jest menedżer zabezpieczeń, oba rozwiązania wymagają uprawnienia ReflectPermission("newProxyInPackage.{nazwa pakietu}"), aby uniknąć wyjątku SecurityException.

W poniższym przykładzie pokazano, jak można zmienić kod, jeśli metoda proxyClass tworzy instancję interfejsu niepublicznego:

Kod oryginalny:
< span class="Kod"> < span class= "JavaKeyword"> public < /span> < span class="JavaType"> Object < /span> instantiateClass(< span class= "JavaType"> Class < ?> < /span> proxyClass, < span class="JavaType">InvocationHandler< /span> handler) throws < span class= "JavaType"> Exception < /span> {

Object o=null;

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

Rozwiązanie 1:
< span class="Code"> < span class= "JavaKeyword"> public < /span> < span class="JavaType"> Obiekt < /span> instantiateClass(< span class= "JavaType"> Klasa < ?> < /span> proxyClass, < span class="JavaType">InvocationHandler< /span>) throws < span class= "JavaType"> Wyjątek < /span> {

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;
}

Rozwiązanie 2:
< span class="Code"> < span class= "JavaKeyword"> public < /span> < span class="JavaType"> Obiekt < /span> instantiateClass(< span class= "JavaType"> Klasa < ?> < /span> proxyClass, < span class="JavaType">InvocationHandler< /span>) throws < span class= "JavaType"> Wyjątek < /span> {

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

Więcej informacji na ten temat można znaleźć w opisie następujących klas w dokumentacji języka Java: