Avatar ·

Не запускается JAR-файл: "no main manifest attribute" — что делать?

Всем привет! Я новичок в Java и пытаюсь собрать простой калькулятор в JAR-файл, чтобы запускать его двойным кликом или через консоль. Компиляция проходит успешно, но при запуске java -jar myapp.jar вылетает ошибка: "no main manifest attribute, in myapp.jar". Вот структура моего проекта: ``` src/ com/ myapp/ Main.java Calculator.java ``` Main.java: ```java package com.myapp; public class Main { public static void main(String[] args) { System.out.println("Калькулятор запущен!"); Calculator calc = new Calculator(); System.out.println("2 + 3 = " + calc.add(2, 3)); } } ``` Calculator.java: ```java package com.myapp; public class Calculator { public int add(int a, int b) { return a + b; } } ``` Я компилирую классы: ``` javac -d out src/com/myapp/*.java ``` Потом создаю JAR: ``` jar cf myapp.jar -C out . ``` В папке out лежат .class файлы в правильной структуре (com/myapp/). Но при запуске — ошибка. Что я делаю не так? Нужно ли создавать какой-то специальный файл? Я слышал про манифест, но не понимаю, как его добавить. Помогите, пожалуйста! <<>>

Причина ошибки: отсутствует точка входа в манифесте

Ошибка no main manifest attribute означает, что внутри JAR-файла нет информации о том, какой класс содержит метод main(). JAR — это просто ZIP-архив с особым файлом META-INF/MANIFEST.MF, который хранит метаданные. Если в этом файле не указана строка Main-Class, JVM не знает, с какого класса начинать выполнение.

Решение: создаём манифест вручную

Самый простой способ — указать точку входа прямо при создании JAR с помощью опции e (entry point):

jar cfe myapp.jar com.myapp.Main -C out .

Где com.myapp.Main — полное имя класса с методом main. После этого в манифесте автоматически появится строка:

Main-Class: com.myapp.Main

Теперь запускайте:

java -jar myapp.jar

Альтернативный способ: файл MANIFEST.MF вручную

Если вы хотите больше контроля, создайте текстовый файл manifest.txt в корне проекта:

Main-Class: com.myapp.Main

Важно: файл должен заканчиваться пустой строкой (переводом строки), иначе JAR может проигнорировать последнюю строку.

Затем создайте JAR с указанием этого файла:

jar cfm myapp.jar manifest.txt -C out .

Проверка манифеста

Убедиться, что манифест создан правильно, можно командой:

jar tf myapp.jar META-INF/MANIFEST.MF

Или вывести содержимое:

unzip -p myapp.jar META-INF/MANIFEST.MF

В выводе вы должны увидеть:

Manifest-Version: 1.0
Created-By: 11.0.16 (Oracle Corporation)
Main-Class: com.myapp.Main

Распространённые ошибки

  • Описание класса с пакетом: обязательно указывайте полное имя — com.myapp.Main, а не просто Main.
  • Путь в JAR: убедитесь, что внутри JAR файлы лежат по пути com/myapp/Main.class, а не в корне.
  • Кодировка манифеста: используйте только ASCII-символы, никакой кириллицы в названиях классов.
  • Права доступа: файл манифеста должен быть читаемым, и не забудьте про пустую строку в конце.

После исправления ваш калькулятор успешно запустится и выведет:

Калькулятор запущен!
2 + 3 = 5
<<>>

Использование сборочных инструментов (Maven/Gradle)

Если вы планируете серьёзно заниматься Java-разработкой, рекомендую сразу освоить систему сборки. Она автоматически решает проблему манифеста и многие другие. Вот пример для Maven:

Добавьте в pom.xml плагин сборки:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <configuration>
                <archive>
                    <manifest>
                        <mainClass>com.myapp.Main</mainClass>
                    </manifest>
                </archive>
            </configuration>
        </plugin>
    </plugins>
</build>

После этого команда mvn package создаст JAR с правильным манифестом. Преимущества:

  • Автоматическое управление зависимостями
  • Генерация манифеста с указанием classpath
  • Возможность создавать "fat JAR" (со всеми библиотеками внутри)

Для Gradle аналогично:

jar {
    manifest {
        attributes 'Main-Class': 'com.myapp.Main'
    }
}

Такой подход избавляет от ручного создания манифеста и подходит для проектов любого размера.