Невозможно экспортировать пакет из модуля java.base

Использование IDEA-EAP для экспериментов по разработке JDK9.

Я получаю следующую ошибку -

Error:(3, 20) java: package jdk.internal.misc is not visible  
(package jdk.internal.misc is declared in module java.base, which does
not export it to module com.jigsaw.npe)

Определение класса как -

package experiment;
import jdk.internal.misc.Unsafe;

public class CompareAndSwap {

    static Unsafe UNSAFE = Unsafe.getUnsafe();
    ...
}

Я попытался включить файл module-info.java в модуль, созданный с помощью IDE, со следующими операторами:

module com.jigsaw.npe {
    requires java.base;
}

Структура каталогов теперь выглядит так, как показано на картинке -

Структура каталогов

IDE, однако, отражает module-info.java как неиспользуемый, и, вероятно, это причина того, что я не могу определить module com.jigsaw.npe, как описано выше.

Ищу помощь о том, как правильно разместить module-info.java и / или что-то еще, кроме того, что я пропустил.


person Naman    schedule 01.03.2017    source источник
comment
@StefanZobel, что именно делает команда и есть ли для этого предварительные условия?   -  person Naman    schedule 01.03.2017
comment
У вас все в порядке, и это не имеет ничего общего с IntelliJ. Я рекомендую отредактировать вопрос (и теги), чтобы удалить эту часть.   -  person Nicolai Parlog    schedule 01.03.2017


Ответы (2)


Ответ Николая верен в отношении методов, необходимых для экспорта неэкспортированного пакета из модуля java.base или из любого другого модуля.

Но если целью является использование Unsafe, способ сделать это - использовать sun.misc.Unsafe, который экспортируется модулем jdk.unsupported. Если вы компилируете свой код для безымянного модуля, вам не нужно делать ничего особенного в отношении модулей, чтобы получить к нему доступ. Если вы компилируете код в модуле, вам нужно добавить

requires jdk.unsupported;

в ваш module-info.java файл.

Чтобы использовать Unsafe, вы должны применить технику отражения setAccessible, чтобы получить доступ к полю, что аналогично тому, что вы делали в предыдущих выпусках JDK:

import sun.misc.Unsafe;

...

Field theUnsafeField = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafeField.setAccessible(true);
Unsafe theUnsafe = (Unsafe)theUnsafeField.get(null);

Несмотря на то, что Unsafe находится в модуле jdk.unsupported, этот метод поддерживается в JDK 9 в соответствии с JEP 260.

person Stuart Marks    schedule 03.03.2017
comment
А как насчет warning: Unsafe is internal proprietary API and may be removed in a future release? Разве эти два не одинаковы по функциональности? - person Gayan Weerakutti; 29.05.2018
comment
@reversiblean Нет, предупреждение внутреннего проприетарного API - это на самом деле другое предупреждение. Он был выпущен javac еще до модульной системы - по крайней мере, я вижу это при компиляции с JDK 7 или JDK 8. Таким образом, это не имеет ничего общего с доступностью модуля. Он выдается, потому что javac может видеть, что программа обращается к типам в пространстве имен sun.*, которые являются внутренними проприетарными API, которые могут быть изменены. - person Stuart Marks; 30.05.2018
comment
Да, я понимаю. Я имел в виду, что jdk.internal.misc.Unsafe и sun.misc.Unsafe одинаковы, несмотря на различия в доступности? - person Gayan Weerakutti; 30.05.2018
comment
Нет, они разные. sun.misc.Unsafe находится в модуле jdk.unsupported и экспортируется. jdk.internal.misc.Unsafe находится в модуле java.base и не экспортируется. sun.misc.Unsafe - это минимальное подмножество внутреннего. Идея состоит в том, чтобы раскрыть минимальный набор небезопасных API, которые фактически используются существующими внешними библиотеками и фреймворками. По мере добавления поддерживаемых общедоступных API-интерфейсов API-интерфейсы будут удалены из sun.misc.Unsafe. jdk.internal.misc.Unsafe продолжает развиваться, но на самом деле он предназначен только для внутреннего использования. - person Stuart Marks; 31.05.2018

Модуль java.base не выполняет экспорт пакет jdk.internal.misc., поэтому тип jdk.internal.misc.Unsafe не доступен - как следствие компиляция не выполняется.

Вы можете заставить его экспортировать пакет, добавив следующий параметр командной строки:

# if you want to access it from com.jigsaw.npe only:
--add-exports java.base/jdk.internal.misc=com.jigsaw.npe
# if you want to access from all code:
--add-exports java.base/jdk.internal.misc=ALL-UNNAMED

Это нужно будет сделать при компиляции (javac) и при запуске (java) кода.

person Nicolai Parlog    schedule 01.03.2017
comment
--add-exports больше не существует - person madduci; 02.11.2017
comment
Да. Позвоните java -X и посмотрите: --add-exports <module>/<package>=<target-module>(,<target-module>)* - person Nicolai Parlog; 02.11.2017
comment
да, как параметр в командной строке, он существует, но если вы установите параметры java с помощью --add-exports, он не работает, жалуясь, что это неизвестный аргумент командной строки - person madduci; 03.11.2017
comment
да, как вариант в командной строке, это именно то, что я утверждал, и ничего больше. - person Nicolai Parlog; 03.11.2017
comment
Можем ли мы как-то добавить его в сборку maven? - person Akshay Hazari; 30.03.2021
comment
@AkshayHazari Да, проверьте документацию для подключаемого модуля компилятора Maven (maven.apache.org/plugins/maven-compiler-plugin/examples/) и плагин Maven Surefire (maven.apache.org/surefire/maven-surefire-plugin/examples/), чтобы узнать, как добавить команду. строчные флаги. - person Nicolai Parlog; 06.04.2021