Weblogi c - Почему Java ClassLoader не загружает классы из jar-файлов, упомянутых в jar-файле пустого манифеста - PullRequest
0 голосов
/ 24 апреля 2020

Недавно я столкнулся со сценарием, в котором у нас будет пустой jar-файл манифеста (т. Е. Jar с просто META-INF / MANIFEST.MF с атрибутом Class-Path), ссылающийся на другой файл jar где-нибудь в файловой системе. Я полагаю, что этот jar-файл манифеста был создан, чтобы действовать как мягкая ссылка на указанный jar-файл версии c, чтобы потребителю не приходилось иметь дело с незначительными изменениями версий реализации jar-файла.

manifest.jar:-
----META-INF/
--------MANIFEST.MF

Actual version specific implementation jar (test-1.1.jar):-
----META-INF/
--------MANIFEST.MF
----test/
--------Test1.class

Включая manifest.jar в classpath в приложении не загружает фактическую реализацию jar и, следовательно, я вижу ClassNotFoundException. Любая идея, почему он не загружается и как я могу загрузить эту банку, как ожидалось?

Обновление :
Я пробовал это с образцом исполняемого файла jar и его (sun.mis c .Launcher $ AppClassLoader), кажется, загружает класс, как и ожидалось. Ссылка просто на manifest.jar в Class-Path, в свою очередь, включает в себя фактическую реализацию jar.
Кроме того, я обнаружил, что у нас есть устаревший загрузчик пользовательских классов для проекта, не уверенный, вызывает ли это странное поведение.

По умолчанию, разве не следует позаботиться о ссылках на другие jar-файлы из manifest.jar?
Есть ли способ проверить, действительно ли этот пользовательский загрузчик классов ссылается на jar-файлы, упомянутые в Class-Path?

Ответы [ 2 ]

1 голос
/ 24 апреля 2020

При использовании java -jar somejar.jar путь к классу устанавливается следующим образом:

  • Переменная окружения CLASSPATH равна полностью игнорируется .
  • -cp / -classpath ключ полностью игнорируется .
  • Запись Class-Path в манифесте банка, который вы указали явно , т.е. somejar.jar читается, разбивается в пробелах любые относительные пути разрешаются относительно каталога, в котором находится jar, и который используется как classpath.
  • Запись Class-Path в любом другом файле jar, включая файлы jar, перечисленные в Class-Path запись somejar.jar is полностью игнорируется .
  • Запись Main-Class в манифесте somejar.jar читается, найденная там строка загружается как класс, а ее основной метод - вызывается. Любые записи Main-Class в любых банках, которые вы упомянули в записи Class-Path, полностью игнорируются .

Другими словами, эта концепция прокси не может действительно работать. Кувшин, который вы вставили в java -jar thejar.jar , должен иметь атрибут Main-Class , а должен перечислить все необходимые банки для запуска этого приложения в атрибуте Class-Path .

Если вы используете это вместо: java -cp somejar.jar:lib/dep1.jar:lib/dep2.jar:etc com.foo.Main, тогда манифест полностью игнорируется , и поэтому все, что вы настроили в атрибуте Class-Path или Main-Class любого манифеста, здесь не имеет значения .

0 голосов
/ 25 апреля 2020

Я думаю, что то, что вы наблюдаете, может быть объяснено разделом JAR-файла spe c атрибута Class-Path .

В частности:

"В настоящее время URL-адреса должны относиться к базе кода файла JAR по соображениям безопасности. Таким образом, удаленные необязательные пакеты будут создаваться из той же базы кода, что и приложение."

"Каждый относительный URL-адрес сопоставляется с базой кода, из которой было загружено содержащее приложение или библиотека. Если полученный URL-адрес недействителен или ссылается на ресурс, который не может быть найден, он игнорируется."

Итак, если атрибут Class-Path в файле MANIFEST.MF для manifest.jar использует абсолютные URL-адреса или URL-адреса, начинающиеся с "/", или если они не разрешаются относительно местоположения manifest.jar Сам по себе соответствующие JAR и т. д. c не будут добавлены во внутренний путь к классам. Они молча игнорируются.

Это произошло бы, если бы вы просто скопировали manifest.jar в свой проект ...

...