Java: пакет `sun.awt.image` устарел?

Я хотел использовать некоторые коды, использующие sun.awt.image.PNGImageDecoder в моем проекте. Проблема в том, что исходный код основан на Java 8, а мой проект использует JDK 9+ (11). Итак, я получил эту ошибку:

Пакет 'sun.awt.image' объявлен в модуле 'java.desktop', который не экспортирует его в безымянный модуль.

для import sun.awt.image.* и:

Символ объявлен в модуле 'java.desktop', который не экспортирует пакет 'sun.awt.image'

для использования PNGImageDecoder или ImageDecoder и т. д.

После некоторых усилий по поиску решения я обнаружил несколько похожих ситуаций, которые предлагают добавить файл requires java.desktop; в файл module-info.java (например, в этом случае и в этом случае). Но, как я понял, это решение может быть полезно только тогда, когда в вашем проекте уже есть файл module-info.java и в нем отсутствует один используемый модуль.

В моем проекте еще не было этого файла (обратите внимание на «безымянный модуль» в первом сообщении об ошибке). Насколько я знаю, это означает, что все модули импортируются автоматически. Таким образом, добавление этого файла и добавление этой строки не имело никакого эффекта, кроме (изменения сообщения об ошибке и) возникновения некоторых подобных проблем для других частей моего кода (которые, конечно, можно было решить, добавив необходимые модули в файл module-info.java).

Конечно, я импортировал все модули в папку jmods (JDK 11), но проблема не решилась:

requires java.base;
requires java.compiler;
requires java.datatransfer;
requires java.desktop;
requires java.instrument;
requires java.logging;
requires java.management;
requires java.management.rmi;
requires java.naming;
requires java.net.http;
requires java.prefs;
requires java.rmi;
requires java.scripting;
requires java.se;
requires java.security.jgss;
requires java.security.sasl;
requires java.smartcardio;
requires java.sql;
requires java.sql.rowset;
requires java.transaction.xa;
requires java.xml.crypto;
requires java.xml;
requires jdk.accessibility;
requires jdk.aot;
requires jdk.attach;
requires jdk.charsets;
requires jdk.compiler;
requires jdk.crypto.cryptoki;
requires jdk.crypto.ec;
requires jdk.crypto.mscapi;
requires jdk.dynalink;
requires jdk.editpad;
requires jdk.hotspot.agent;
requires jdk.httpserver;
requires jdk.internal.ed;
requires jdk.internal.jvmstat;
requires jdk.internal.le;
requires jdk.internal.opt;
requires jdk.internal.vm.ci;
requires jdk.internal.vm.compiler;
requires jdk.internal.vm.compiler.management;
requires jdk.jartool;
requires jdk.javadoc;
requires jdk.jcmd;
requires jdk.jconsole;
requires jdk.jdeps;
requires jdk.jdi;
requires jdk.jdwp.agent;
requires jdk.jfr;
requires jdk.jlink;
requires jdk.jshell;
requires jdk.jsobject;
requires jdk.jstatd;
requires jdk.localedata;
requires jdk.management.agent;
requires jdk.management.jfr;
requires jdk.management;
requires jdk.naming.dns;
requires jdk.naming.rmi;
requires jdk.net;
requires jdk.pack;
requires jdk.rmic;
requires jdk.scripting.nashorn;
requires jdk.scripting.nashorn.shell;
requires jdk.sctp;
requires jdk.security.auth;
requires jdk.security.jgss;
requires jdk.unsupported.desktop;
requires jdk.unsupported;
requires jdk.xml.dom;
requires jdk.zipfs;

Я знаю, что этот пакет (sun.awt.image) существует в модуле java.desktop (JDK 11), но не знаю, как получить к нему доступ.

Я использую IntelliJ IDEA в качестве IDE.


person Mir-Ismaili    schedule 16.12.2018    source источник
comment
Вы не должны использовать классы sun.* или com.sun.* в своей программе; они являются недокументированными внутренними классами JDK и могут изменяться в любом выпуске. Их использование может сделать вашу программу несовместимой с другими версиями Java. См. Использовать проприетарные Java-классы?   -  person Jesper    schedule 16.12.2018
comment
@Джеспер - Спасибо. Если вы опубликуете свой комментарий в качестве ответа, я могу принять его. Я также благодарю nullpointer за хороший ответ.   -  person Mir-Ismaili    schedule 16.12.2018


Ответы (2)


Вы не должны использовать классы sun.* или com.sun.* в своей программе; они являются недокументированными внутренними классами JDK и могут изменяться в любом выпуске.

Их использование может сделать вашу программу несовместимой с другими версиями Java.

См.: Не рекомендуется использовать проприетарные классы Java?

person Jesper    schedule 16.12.2018
comment
Конечно, в идеальном мире, но иногда вам нужно сделать это, чтобы добиться цели. - person Paul Taylor; 28.03.2020
comment
@PaulTaylor С риском того, что ваше программное обеспечение перестанет работать с новой версией Java. - person Jesper; 28.03.2020
comment
Конечно, но в наши дни вы обычно упаковываете свое приложение с версией Java, поэтому вы можете быть уверены, что ваше приложение работает с той версией Java, с которой вы его распространяете. Я бы использовал солнечные классы только тогда, когда это единственный способ обойти проблему, это, конечно, не то, что я хотел бы делать. - person Paul Taylor; 28.03.2020

Он инкапсулирован!

Проблема точно не будет решена со всеми модулями из JDK.

Я знаю, что этот пакет (sun.awt.image) существует в модуле java.desktop (JDK 11), но не знаю, как получить к нему доступ.

Суть проблемы заключается в том, что хотя класс PNGImageDecoder и пакет, к которому он принадлежит sun.awt.image, являются частью модуля java.desktop, модуль решил не экспортировать его ни в какие внешняя библиотека, использующая его.

Выбор абстрагирования таких классов (sun.*) был преднамеренным и хорошо задокументирован в примечаниях к выпуску Java-9, а обоснование указано в JEP-260#Инкапсулировать большинство внутренних API.


Сказав это, временным довольно хакерским решением будет добавление

--add-exports=java.desktop/sun.awt.image=<yourModuleName>

к вашим аргументам командной строки. Желательно, чтобы вы искали альтернативный способ того, чего вы пытаетесь достичь, используя класс PNGImageDecoder.


Последняя его часть, безымянный модуль — это место, где фактический код (будь то ваше приложение или любые его зависимости) пытается получить доступ к этому классу PNGImageDecoder. Так что подумайте об этом так: приведенный выше аргумент командной строки для вашего варианта использования приводит к следующему:

--add-exports=java.desktop/sun.awt.image=ALL-UNNAMED
person Naman    schedule 16.12.2018