Java не может найти класс в модульном файле jar, но javap может

У меня есть простой привет мир, который я пытаюсь встроить в модульный jar-файл, чтобы протестировать запуск jlink. Я не могу ни запустить файл jar, ни создать для него образ с помощью jlink.

Я работаю в Windows и использую Java 21.

Вот Java-файлы в проекте.

$ find src/main/java -name '*\.java'
src/main/java/com/foo/bar/demoapp/App.java
src/main/java/module-info.java

package com.foo.bar.demoapp;

public class App
{
    public static void main( String[] args )
    {
        System.out.println("hello hello");
    }
}

module demoapp {
    exports com.foo.bar.demoapp;
}

Я использую Maven 3.9.6, и мой файл pom довольно прост. Там указано maven.compiler.(source|target)=21. Он устанавливает версию плагина компилятора 3.13.0. Он устанавливает для плагина jar версию 3.1.2 и указывает класс App как mainClass.

<configuration>
<archive>
  <manifest>
    <mainClass>com.foo.bar.demoapp.App</mainClass>
  </manifest>
</archive>
</configuration>

Я проверил, что файл jar содержит ожидаемое содержимое.

$ unzip -l jars/demo-app-1.0-SNAPSHOT.jar
Archive:  jars/demo-app-1.0-SNAPSHOT.jar
  Length      Date    Time    Name
---------  ---------- -----   ----
      116  2024-04-08 12:30   META-INF/MANIFEST.MF
      552  2024-04-08 12:30   com/foo/bar/demoapp/App.class
     5160  2024-04-08 12:09   META-INF/maven/com.foo.bar/demo-app/pom.xml
       64  2024-04-08 12:30   META-INF/maven/com.foo.bar/demo-app/pom.properties
      283  2024-04-08 12:30   module-info.class

Я использовал javap, чтобы убедиться, что класс информации о модуле отображает основной класс как требуется.

$ javap -verbose --module demoapp --module-path jars module-info
Classfile jar:file:///C:/Users/wrobert1/dev/foo/demo-app/jars/demo-app-1.0-SNAPSHOT.jar!/module-info.class
  Last modified Apr 8, 2024; size 283 bytes
  SHA-256 checksum 004814b6bbe32c09ecba1fe2a02289d5e4b33a14426856ca6598e1c256405443
  Compiled from "module-info.java"
module [email protected]
  minor version: 0
  major version: 65
  flags: (0x8000) ACC_MODULE
  this_class: #1                          // "module-info"
  super_class: #0
  interfaces: 0, fields: 0, methods: 0, attributes: 4

... constant pool elided ...

SourceFile: "module-info.java"
Module:
  #6,0                                    // demoapp
  #8                                      // 1.0-SNAPSHOT
  1                                       // requires
    #9,8000                                 // "java.base" ACC_MANDATED
    #11                                     // 21.0.1
  1                                       // exports
    #12,0                                   // com/foo/bar/demoapp
  0                                       // opens
  0                                       // uses
  0                                       // provides
ModuleMainClass: #16                    // com.foo.bar.demoapp.App
ModulePackages:
  #12                                     // com.foo.bar.demoapp

Я также использовал javap, чтобы убедиться, что App.class имеет основную функцию.

$ javap --module demoapp --module-path jars com.foo.bar.demoapp.App
Compiled from "App.java"
public class com.foo.bar.demoapp.App {
  public com.foo.bar.demoapp.App();
  public static void main(java.lang.String[]);
}

Учитывая все это, когда я пытаюсь запустить файл jar, я получаю исключение ClassNotFoundException.

$ java --module-path jars com.foo.bar.demoapp.App
Error: Could not find or load main class com.foo.bar.demoapp.App
Caused by: java.lang.ClassNotFoundException: com.foo.bar.demoapp.App

И jlink не работает, вероятно, по той же причине.

$ jlink --module-path jars --output linked  --add-modules=java.base --launcher startmeup=demoapp/com.foo.bar.demoapp.App
Error: java.lang.IllegalArgumentException: demoapp does not have main class: com.dhl.raf.demoapp.App

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

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
0
59
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

При выполнении основного класса с помощью java один из способов решить эту проблему — указать, какие модули должны быть добавлены из пути к модулю для разрешения.

java --module-path jars --add-modules demoapp com.foo.bar.demoapp.App

Это также будет работать и в случае jlink с чем-то вроде:

jlink --module-path jars --output linked --add-modules=java.base,demoapp --launcher startmeup=demoapp/com.foo.bar.demoapp.App

Альтернативой вашему подходу к использованию javap может быть указание модуля вместе с mainClass, например:

java --module-path jars --module demoapp/com.foo.bar.demoapp.App     

Дополнительную информацию об этом можно получить с помощью самой командной строки java -help.

Этот ответ попадает в точку для запуска Java, но это немного расплывчатый jlink WRT, который кажется немного неудобным. Для работы jlink необходимо также добавить модуль приложения, но нельзя указать путь к классу приложения в опциях --launcher. то есть jlink --module-path jars --output linked --launcher startmeup=demoapp --add-modules=java.base,demoapp работает.

BillRobertson42 08.04.2024 23:18

Насчет jlink, именно это я имел в виду под последней строкой первого раздела ответа. Позвольте мне отредактировать, чтобы сделать это явным.

Naman 09.04.2024 16:05

Другие вопросы по теме