Ewoud
Ewoud

Reputation: 14395

Can't execute jar- file: "no main manifest attribute"

I have installed an application and when I try to run it (it's an executable jar) nothing happens. When I run it from the command line with:

java -jar "app.jar"

I get the following message:

no main manifest attribute, in "app.jar"

Normally, if I had created the program myself, I would have added a main class attribute to the manifest file. But in this case, since the file is from an application, I cannot do that. I also tried extracting the jar to see if I could find the main class, but there are too many classes and none of them has the word "main" in it's name. There must be a way to fix this because the program runs fine on other systems.

Upvotes: 1418

Views: 2564580

Answers (30)

John M
John M

Reputation: 13239

If the jar isn't following the Jar File Specification and specifically the Main-Class attribute, it's not an executable jar.

Upvotes: 9

RidiX
RidiX

Reputation: 928

I am using a Quarkus based application. In my case, this did the trick:

./mvnw package -Dquarkus.package.type=uber-jar

Hope it helps!

Upvotes: 0

Sasanka Panguluri
Sasanka Panguluri

Reputation: 3138

That is because Java cannot find the Main attribute in the MANIFEST.MF file. The Main attribute is necessary to tell Java which class it should use as the application's entry point. Inside the jar file, the MANIFEST.MF file is located in META-INF folder. Wondering how you could look at what's inside a jar file? Open the jar file with WinRAR.

The main attribute inside the MANIFEST.MF looks like this:

Main-Class: <packagename>.<classname>

You get this "no main manifest attribute" error when this line is missing from the MANIFEST.MF file.

It's really a huge mess to specify this attribute inside the MANIFEST.MF file.

Update


I have just found a really neat way to specify the application's entry point in Eclipse :

  1. Select File > Export..
  2. Select JAR file then Next
  3. Give it a name in the next window then Next
  4. Select Next again
  5. You'll see "Select the class of the application entry point", just pick a class and Eclipse will automatically build a cool MANIFEST.MF for you.

enter image description here

Upvotes: 72

David
David

Reputation: 2346

For maven, this is what solved it (for me, for a Veetle codebase on GitHub):

<build>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-shade-plugin</artifactId>
      <version>2.0</version>
      <executions>
        <execution>
          <phase>package</phase>
          <goals>
            <goal>shade</goal>
          </goals>
          <configuration>
            <transformers>
              <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                <mainClass>org.lazydevs.veetle.api.VeetleAPI</mainClass>
              </transformer>
            </transformers>
          </configuration>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>

Upvotes: 39

Naga Srinu Kapusetti
Naga Srinu Kapusetti

Reputation: 1631

I had the same issue and adding the following lines to the pom file made it works. The plugin will make sure that the build process of your application is made with all the necessary steps.

<build>
  <plugins>
    <plugin>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-maven-plugin</artifactId>
    </plugin>
  </plugins>
</build>

Upvotes: 67

CodeBrew
CodeBrew

Reputation: 7207

Alternatively, you can use maven-assembly-plugin, as shown in the below example:

<plugin>
  <artifactId>maven-assembly-plugin</artifactId>
  <executions>
    <execution>
      <phase>package</phase>
      <goals>
        <goal>single</goal>
      </goals>
    </execution>
  </executions>
  <configuration>
    <archive>
      <manifest>
        <addClasspath>true</addClasspath>
        <mainClass>com.package.MainClass</mainClass>
      </manifest>
    </archive>
    <descriptorRefs>
      <descriptorRef>jar-with-dependencies</descriptorRef>
    </descriptorRefs>
  </configuration>
</plugin> 

In this example all the dependency jars as specified in section will be automatically included in your single jar. Note that jar-with-dependencies should be literally put as, not to be replaced with the jar file names you want to include.

Upvotes: 189

ingconti
ingconti

Reputation: 11666

I have similar questions from my students, but I have added this answer as is a bit different, it covers another HOT topic: How to build a JAR form IntelliJ JavaFX project since IntelliJ in 2023 allows to build a fast JavaFX project.

Some ideas:

  • Use maven
  • Start form IntelliJ
  • Use maven power to make a jar with shaved plugs in
  • Use cmd liken or double-click

Without filling all at the page with HTML / code, I can make a little project with detailed PDF, step by step.

(From IntelliJ JavaFX demo to JAR .pdf) https://github.com/ingconti/JavaFXMinimalClickableDemo

Hope it helps.

Upvotes: 1

Mukit09
Mukit09

Reputation: 3409

I was getting the same error when executing mvn package. This is how I solved the problem.

I was using the maven-multi-module. I was facing this issue because I added below part in parent pom by mistake.

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
</plugin>

Then replacing this to submodules pom.xml from parent pom solved my problem.

Upvotes: 2

Сергей
Сергей

Reputation: 130

First I created an artifact using this instruction: https://www.jetbrains.com/help/idea/compiling-applications.html#package_into_jar

Then when this error occurred this short video helped me: https://www.youtube.com/watch?v=AeN1yLSjfLU In short, the essence of the answer is as follows. Even though we have a file MANIFEST.MF lying (for example) on the way to src/main/java/com.example.demo.META-INF/MANIFEST.MF in which there is a string indicating the path to the Main class:

Main-Class: com.example.demo.DemoApplication

When we building an artifact, there is a file MANIFEST.MF in the interior. For some reason he does not have inside himself this string. To remove this error, we need to manually get this MANIFEST.MF from the artifact/archive and add this path from the original MANIFEST.MF to it.

Upvotes: 2

likejudo
likejudo

Reputation: 3736

If you are using IntelliJ, then JEtBrains has detailed the steps to fix this over here

https://www.jetbrains.com/help/idea/2022.2/convert-a-regular-project-into-a-maven-project.html#develop_with_maven

Create an executable JAR You can conclude the following optional steps to create an executable JAR.

Click the Build Project icon to build project. IntelliJ IDEA generates target folder. Note that IntelliJ IDEA only compiles sources and doesn't create either JAR file or Manifest file.

Create a Manifest file in the resources directory.

Right-click the directory, select New | Directory to create the META-INF subdirectory. Then right-click the subdirectory, select New | File to create the MANIFEST.MF file.

the Manifest file Open the MANIFEST.MF file in the editor and add information about your main class.

Check the following code:

Main-Class: com.company.MyApp Alternatively, we can ask Maven to add this line of code into the MANIFEST.MF file with the following code in pom.xml:

org.apache.maven.plugins maven-jar-plugin com.company.MyApp In your POM specify the Manifest file information, so you can use Maven to generate an executable jar file.

POM with manifest

Upvotes: 0

Ueffes
Ueffes

Reputation: 164

In my case - I work on a multi-module project - I could introduced the issue in the following way:

I added this into the parent pom.xml, which caused the issue. Namely, the skip with value true:

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <!--
                besides hindering the packaging, this also skips running the app after build when calling spring-boot:run. You have to enable it in the
                corresponding module by setting skip to false, there.
                -->
                <skip>true</skip>
            </configuration>
        </plugin>
    </plugins>
</build>

I fixed the issue by adding the same configuration to the modules that i wanted to be packaged as a jar, but changed the value of skip to false:

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <version>${spring-boot.version}</version>
    <configuration>
        <mainClass>${project.mainClass}</mainClass>
        <layout>ZIP</layout>
        <skip>false</skip>
    </configuration>
    <executions>
        <execution>
            <goals>
                <goal>repackage</goal>
            </goals>
        </execution>
        <execution>
            <id>build-info</id>
            <goals>
                <goal>build-info</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Upvotes: 3

Olivier Refalo
Olivier Refalo

Reputation: 51535

First, it's kind of weird, to see you run java -jar "app" and not java -jar app.jar

Second, to make a jar executable... you need to jar a file called META-INF/MANIFEST.MF

the file itself should have (at least) this one liner:

Main-Class: com.mypackage.MyClass

Where com.mypackage.MyClass is the class holding the public static void main(String[] args) entry point.

Note that there are several ways to get this done either with the CLI, Maven, Ant or Gradle:

For CLI, the following command will do: (tks @dvvrt)

jar cmvf META-INF/MANIFEST.MF <new-jar-filename>.jar  <files to include>

For Maven, something like the following snippet should do the trick. Note that this is only the plugin definition, not the full pom.xml:

Latest doc on this plugin: see https://maven.apache.org/plugins/maven-jar-plugin/

<build>
  <plugins>
    <plugin>
      <!-- Build an executable JAR -->
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-jar-plugin</artifactId>
      <version>3.1.0</version>
      <configuration>
        <archive>
          <manifest>
            <addClasspath>true</addClasspath>
            <classpathPrefix>lib/</classpathPrefix>
            <mainClass>com.mypackage.MyClass</mainClass>
          </manifest>
        </archive>
      </configuration>
    </plugin>
  </plugins>
</build>

(Pick a <version> appropriate to your project.)

For Ant, the snippet below should help:

<jar destfile="build/main/checksites.jar">
  <fileset dir="build/main/classes"/>
  <zipfileset includes="**/*.class" src="lib/main/some.jar"/>
  <manifest>
    <attribute name="Main-Class" value="com.acme.checksites.Main"/>
  </manifest>
</jar>

Credits Michael Niemand -

For Gradle:

plugins {
    id 'java'
}

jar {
    manifest {
        attributes(
                'Main-Class': 'com.mypackage.MyClass'
        )
    }
}

Upvotes: 1406

user13769010
user13769010

Reputation:

If your on maven and your pom.xml is something like this

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
      <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.3</version>
        <relativePath/> <!-- lookup parent from repository -->
      </parent>
      <groupId>com.example</groupId>
      <artifactId>demo</artifactId>
      <version>0.0.1-SNAPSHOT</version>
      <name>demo</name>
      <properties>
        <java.version>11</java.version>
      </properties>
      <dependencies>
        <!-- dependencies -->
      </dependencies>
      <build>
        <pluginManagement>
          <plugins>
            <plugin>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
          </plugins>
        </pluginManagement>
      </build>
    </project>

just comment the pluginManagement that will result you in the following pom.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
      <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.3</version>
        <relativePath/> <!-- lookup parent from repository -->
      </parent>
      <groupId>com.example</groupId>
      <artifactId>demo</artifactId>
      <version>0.0.1-SNAPSHOT</version>
      <name>demo</name>
      <properties>
        <java.version>11</java.version>
      </properties>
      <dependencies>
        <!-- dependencies -->
      </dependencies>
      <build>
        <plugins>
          <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
          </plugin>
        </plugins>
      </build>
    </project>

Upvotes: 2

Lonely Solitary
Lonely Solitary

Reputation: 139

For my case the problem is <pluginManagement> under <build> makes things cannot work properly.

My original pom.xml:

<build>
  <pluginManagement>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        ...
        ...
        ...
  </pluginManagement>
</build>

After removing <pluginManagement>, the error is gone.

Upvotes: 4

MobileEvangelist
MobileEvangelist

Reputation: 2628

Simply add this to your java module's build.gradle. It'll create executable jar. It will include dependent libraries in archive.

jar {
  manifest { 
    attributes "Main-Class": "com.company.application.Main"
  }  

  from {
    configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
  }
}

This will result in [module_name]/build/libs/[module_name].jar file. I tested this with shell.

Upvotes: 0

Lumito
Lumito

Reputation: 520

Create the folder META-INF and the file MANIFEST.MF in that folder with this content:

Manifest-Version: 1.0
Class-Path: .
Main-Class: [YOUR_MAIN_CLASS]

Then compile including that manifest file.

Upvotes: 0

Yury Finchenko
Yury Finchenko

Reputation: 1075

The MAVEN problem is that its try to include the first MANIFEST.MF file from first library from dependencies instead of THE OUR OWN MANIFEST.MF WHEN YOU USE ARTIFACTS!.

  1. Rename yourjar.jar to yourjar.zip
  2. Open MANIFEST.MF file from META-INF\MANIFEST.MF
  3. Copy the real MANIFEST.MF that already generate in your project by MAVEN That include somelike that:

    Manifest-Version: 1.0 Main-Class: yourpacket.yourmainclass (for exmaple info.data.MainClass)

  4. Replace the content of MANIFEST.MF from youjar.zip with it.

  5. Rename yourjar.zip to yourjar.jar back.
  6. Now java -jar yourjar.jar work perfectly.

OR!

Simple create you own MANIFEST.MF and:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <version>3.2.0</version>
    <configuration>
        <archive>
            <manifestFile> Your path like: src/main/resources/META-INF/MANIFEST.MF </manifestFile>
            <index>true</index>
                <manifest>
                    <addClasspath>true</addClasspath>
                </manifest>
        </archive>
    </configuration>
</plugin>

But if you use maven panel (or maven command line) you can force it to generate own manifest and include it into JAR file.

  1. Add to the you pom.xml's build section this code:

    <plugins>
        <plugin>
    
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-assembly-plugin</artifactId>
        <version>3.2.0</version>
        <executions>
            <execution>
                <phase>package</phase>
                <goals>
                    <goal>single</goal>
                </goals>
            </execution>
        </executions>
    
        <configuration>
            <descriptorRefs>
                <descriptorRef>jar-with-dependencies</descriptorRef>
            </descriptorRefs>
    
            <archive>
    
                <index>true</index>
    
                <manifest>
                    <addClasspath>true</addClasspath>
                    <mainClass> yourpacket.yourmainclass (for exmaple info.data.MainClass)</mainClass>
                </manifest>
                <manifestEntries>
                    <mode>development</mode>
                    <url>${project.url}</url>
                </manifestEntries>
            </archive>
        </configuration>
    </plugin>
    

  2. Open the MAVEN panel (in Intellij) and execute "Install". It will generate the MANIFEST file and compile property the JAR file with all dependencies into the "Target" folder. Also it will be installed to the local maven repository.

Upvotes: 20

Darshil Shah
Darshil Shah

Reputation: 505

I tried this and it worked for me. mvn clean install package should work.

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <executions>
            <execution>
                <goals>
                    <goal>repackage</goal>
                </goals>
            </execution>
            </executions>
        </plugin>
    </plugins>
</build>

Upvotes: 7

user10356724
user10356724

Reputation:

most of the solutions did not work for me but my instructor helped me out i would like to share his solution here i used kali linux terminal but should be fine in all debian

javac *.java
nano MANIFEST.MF

in the file type

Main-Class: Main or whatever your main file name is (make sure to add package name if it exists)

jar -cvmf MANIFEST.MF new.jar *.class

now to run the file use

java -jar new.jar

or you can go to propeties of file and check

Allow Execution of file as program

double click on it

it helped me while most of the above answers did not

Upvotes: 3

Ritesh Tyagi
Ritesh Tyagi

Reputation: 55

Found a great solution which would help in any such situation, given you just need a runnable jar, which you do in most cases. If your application is running in Intellij Idea follow these steps: 1) Go to module settings and then artifacts, and add a jar and define main class 2) Then go to Build in the menu and click "build artifact" and you get the jar.

This worked even when I changed the source folder and used scala instead of java.

Upvotes: 1

Dave Beauchesne
Dave Beauchesne

Reputation: 121

I found a new solution to bad manifest generation !

  1. Open the jar file with a zip editor like WinRAR
  2. Click on for META-INF

  3. Add or edit

    • Add:

      • Create a text file called MANIFEST.MF in a folder called META-INF and add the following line:

        • Manifest-Version: 1.0
        • Main-Class: package.ex.com.views.mainClassName
      • Save the file and add it to the zip

    • Edit:

      • Drag the file out modify the MANIFEST.MF to add the previous line
  4. Open cmd and type: java -jar c:/path/JarName.jar

It should work fine now !

Upvotes: 7

djangofan
djangofan

Reputation: 29689

I personally think all the answers here are mis-understanding the question. The answer to this lies in the difference of how spring-boot builds the .jar. Everyone knows that Spring Boot sets up a manifest like this, which varies from everyones asssumption that this is a standard .jar launch, which it may or may not be :

Start-Class: com.myco.eventlogging.MyService
Spring-Boot-Classes: BOOT-INF/classes/
Spring-Boot-Lib: BOOT-INF/lib/
Spring-Boot-Version: 1.4.0.RELEASE
Created-By: Apache Maven 3.3.9
Build-Jdk: 1.8.0_131
Main-Class: org.springframework.boot.loader.JarLauncher

Perhaps it needs to executed with org.springframework.boot.loader.JarLauncher on the classpath?

Upvotes: 7

Reihan_amn
Reihan_amn

Reputation: 2747

Just to make one point clear about

Main-Class: <packagename>.<classname>

If you don't have package you have to ignore that part, like this:

Main-Class: <classname>

Upvotes: 2

Abdelsalam Shahlol
Abdelsalam Shahlol

Reputation: 1769

I had this problem and i solved it recently by doing this in Netbeans 8 (Refer to the image below):

Netbeans project properties

  1. go to properties of your project.
  2. click on Run.
  3. specify the main class of your project using browse.
  4. build and run the Jar file.

Upvotes: 1

Binakot
Binakot

Reputation: 308

I got same error just now. If u're using gradle, just add next one in ur gradle.build:

apply plugin: 'java'

jar {
    manifest {
        attributes 'Main-Class': 'com.company.project.MainClass'
    }
}

Where com.company.project.MainClass path to ur class with public static void main(String[] args) method.

Upvotes: 12

MichaelT
MichaelT

Reputation: 61

(first post - so it may not be clean)

This is my fix for OS X 11.6, Maven-based Netbeans 8.2 program. Up to now my app is 100% Netbeans - no tweaking (just a few shell escapes for the impossible!).

Having tried most all of the answers here and elsewhere to no avail, I returned to the art of "use what works".

The top answer here (olivier-refalo thanx) looked like the right place to start but didn't help.

Looking at other projects which did work, I noticed some minor differences in the manifest lines:

  1. addClasspath, classpathPrefix were absent (deleted them)
  2. mainClass was missing the "com." (used the NB -> Project Properties->Run->Main Class->Browse to specify)

Not sure why (I am only 3 months into java) or how, but can only say this worked.

Here is just the modified manifest block used:

    <manifest>
        <mainClass>mypackage.MyClass</mainClass>
    </manifest>

Upvotes: 3

MTA
MTA

Reputation: 809

I had the same issue today. My problem was solved my moving META-INF to the resources folder.

Upvotes: 13

mwag
mwag

Reputation: 4055

The above answers were only partly helpful for me. java -cp was part of the answer, but I needed more specific info on how to identify the class to run. Here is what worked for me:

Step 1: find the class I need to run

jar tf /path/to/myjar.jar | more

The top lines of the result were:

META-INF/
META-INF/MANIFEST.MF
somepath/
somepath/App.class
META-INF/maven/
...

App.class contained the main class to run. I'm not 100% sure if you can always assume the class you need is the first one, but it was for me. If it isn't, I'd imagine it isn't too hard to use grep to exclude library-related results to pare the class list down to a manageable size.

From there it was easy: I just use that path (minus the ".class" suffix):

java -cp /path/to/myjar.jar somepath/App

Upvotes: 3

Fan Yer
Fan Yer

Reputation: 391

Since you've add MANIFEST.MF, I think you should consider the order of Field in this file. My env is java version "1.8.0_91"

and my MANIFEST.MF as here

// MANIFEST.MF
Manifest-Version: 1.0
Created-By: 1.8.0_91 (Oracle Corporation)
Main-Class: HelloWorldSwing

// run
~ java -jar HelloWorldSwing.jar
no main manifest attribute, in HelloWorldSwing.jar

However, this as below run through

Manifest-Version: 1.0
Main-Class: HelloWorldSwing
Created-By: 1.8.0_91 (Oracle Corporation)

//this run swing normally

Upvotes: 2

CodeMonkey
CodeMonkey

Reputation: 4768

I had the same problem. A lot of the solutions mentioned here didn't give me the whole picture, so I'll try to give you a summary of how to pack jar files from the command line.

  1. If you want to have your .class files in packages, add the package in the beginning of the .java.

    Test.java

    package testpackage;
    
    public class Test
    {
        ...
    }
    
  2. To compile your code with your .class files ending up with the structure given by the package name use:

    javac -d . Test.java
    

    The -d . makes the compiler create the directory structure you want.

  3. When packaging the .jar file, you need to instruct the jar routine on how to pack it. Here we use the option set cvfeP. This is to keep the package structure (option P), specify the entry point so that the manifest file contains meaningful information (option e). Option f lets you specify the file name, option c creates an archive and option v sets the output to verbose. The important things to note here are P and e.

    Then comes the name of the jar we want test.jar.

    Then comes the entry point .

    And then comes -C . <packagename>/ to get the class files from that folder, preserving the folder structure.

    jar cvfeP test.jar testpackage.Test -C . testpackage/
    
  4. Check your .jar file in a zip program. It should have the following structure

    test.jar

    META-INF
    | MANIFEST.MF
    testpackage
    | Test.class
    

    The MANIFEST.MF should contain the following

    Manifest-Version: 1.0
    Created-By: <JDK Version> (Oracle Corporation)
    Main-Class: testpackage.Test
    

    If you edit your manifest by hand be sure to keep the newline at the end otherwise java doesn't recognize it.

  5. Execute your .jar file with

    java -jar test.jar
    

Upvotes: 8

Related Questions