2017-01-24 13 views
5

Я использую JDK-9, и я хочу использовать sun.reflect.* пакет в моем коде, но я получаю ниже исключениеКак использовать sun.reflect пакет в jdk9/java-9?

Exception in thread 'main' java.lang.IllegalAccessError : class Test (in moudle: Unnamed Module) cannot access class sun.reflect.Reflaction (in module:java.base), sun.reflect is not exported to Unnamed module 

когда я запускаю ниже пример кода с использованием JDK-9

public static void main(String args[]){ 
    System.out.println(Reflection.getCallerClass(3)); 
} 

ответ

3
java -cp classes -XaddExports:java.base/sun.reflect Test 

Jigsaw (java-9) имеет концепцию модульности, в которой они разработали пакет java.base для компакт-1, и они заключили в капсулу sun.reflect.*. так что sun.reflect.* не может быть доступен снаружи. Благодаря этой причине она дает исключение

Exception in thread 'main' java.lang.IllegalAccessError : class Test (in moudle: Unnamed Module) cannot access class sun.reflect.Reflaction (in module:java.base), sun.reflect is not exported to Unnamed module 

Тем не менее, чтобы обеспечить обратную совместимость, они предусмотрели способ использовать этот пакет, как показано ниже.

java -cp classes -XaddExports:java.base/sun.reflect Test 
+3

Ответ несколько вводит в заблуждение: (1) компактные профили не имеют к этому никакого отношения; (2) он не подходит для всех видов других пакетов; (3) сообщение об ошибке и предлагаемое решение устарели. См. [Мой ответ] (http://stackoverflow.com/a/41824999/2525313). – Nicolai

+1

@Nicolai Ваш ответ устарел. См. [Этот ответ] (http://stackoverflow.com/a/42187227/706317) вместо этого: – ZhekaKozlov

5

Этот ответ устаревшую - ПРОВЕРКА THIS ONE ВМЕСТО!

Особенностью модульной системы является то, что она позволяет разработчикам библиотеки строго инкапсулировать детали реализации из-за новых accessibility rules. Вкратце, большинство типов в пакетах sun.* и com.sun.* больше не будут доступны. Это соответствует Sun и позже Oracle, заявив, что эти пакеты не предназначены для общественного потребления.

Обойти это экспортировать эти пакеты во время компиляции и запуска время с флагом командной строки:

--add-exports java.base/sun.reflect=ALL-UNNAMED 

Это экспортирует пакет sun.reflect из модуля java.base для всех модулей, включая unnamed module, которые это тот, который собирает все классы в пути класса.

+0

Это, я думаю, должно быть '--add-exports jdk.unsupported/sun.reflect = ALL-UNNAMED' – reversiblean

4

Эти пакеты sun.* никогда не были частью официального API и не гарантировались, даже в JVM до Java 9. Будьте готовы к тому, чтобы они полностью исчезли в будущем, даже не могут быть восстановлены с помощью некоторых опций. К счастью, существует официальный API, охватывающий эту функциональность, устраняя необходимость в неофициальных API.

Получить Непосредственный класс вызывающего абонента
Class<?> c = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE) 
         .getCallerClass(); 
Получить n-й вызывающего абонента в стеке (например, третий, как в вашем примере):
Class<?> c = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE).walk(s -> 
    s.map(StackWalker.StackFrame::getDeclaringClass).skip(3).findFirst().orElse(null)); 
6

отлично работает с более новой сборкой OpenJDK 9 EA. Например:

$ java -version 
java version "9-ea" 
Java(TM) SE Runtime Environment (build 9-ea+138) 
Java HotSpot(TM) 64-Bit Server VM (build 9-ea+138, mixed mode) 

$ javac Test.java 
Test.java:5: warning: Reflection is internal proprietary API and may be removed in a future release 
    System.out.println(Reflection.getCallerClass(3)); 
        ^
Note: Test.java uses or overrides a deprecated API. 
Note: Recompile with -Xlint:deprecation for details. 
1 warning 

$ java Test 
null 

Кажется, что это было зафиксировано в 9-еа + 115 сборки в составе JDK-8137058. Поэтому, вероятно, вы используете старую сборку EA. В целом @Holger прав: есть большие шансы, что этот API полностью исчезнет в будущих версиях Java, поэтому рассмотрим возможность перехода на API StackWalker.

+2

Действительно, 'sun.reflect.Reflection' переместился в модуль' jdk.unsupported'. Итак, он будет там, по крайней мере, до Java 10. – ZhekaKozlov

1

Обновление нити с последним выпуском и внесенными изменениями, как указано в документе Migration documentation. Правильно правильно pointed out by @Holger уже.

API-интерфейсы в sun.reflect пакеты, которые остаются доступными в JDK 9 являются:

  • sun.reflect.Reflection::getCallerClass(int) Вместо этого используйте стек-пешеходную API см JEP 259: Stack-Walking API.
  • sun.reflect.ReflectionFactory.newConstructorForSerialization

Эти API являются по умолчанию используется во время выполнения. Они были перемещены в модуль jdk.unsupported, который присутствует в изображениях JRE и JDK. Модули, которым нужны эти API, должны заявлять зависимость от модуля jdk.unsupported.

Остающиеся внутренние API, в sun.misc и sun.reflect пакеты были перемещены, так как они не должны быть доступны. Если вам нужно использовать один из этих внутренних API, вы можете разбить инкапсуляцию, используя опцию командной строки --add-exports. (аналогично answered by @NIrav). Хотя, как было предложено в документах, , этот вариант следует использовать только как временную помощь для миграции.

+0

Если вы новичок в модулях java9, было бы полезно знать, что вам нужно добавить новый файл в свой пакет, называемый module-info.java, который объявляет зависимость от jdk.unsupported. это выглядит так: 'module com.mypackage {требует jdk.unsupported; требуется org.apache.logging.log4j; экспорт com.mypackage; } ' – BrettonW