简体   繁体   中英

Cannot execute jar file

Have some technical trouble with compiling Java jar file with command line.

I have these two .java files in the same directory

// Source.java

package home;

public class Source {

  public Source(){
     System.out.println("This is the source.");
  }

  public static void main(String[] s){
     System.out.println("this is England.");
     System.out.println("ok 1 - Input file close");
     new Source();
     new Other();
     System.exit(3);
  }

}

// Other.java

package home;

public class Other {

  public Other(){
     System.out.println("More source here.");
  }


}

I compile these two files into a .jar file like so:

#!/usr/bin/env bash

javac $(dirname "$0")/*.java
jar cmf MyJar.jar Manifest.txt *.class

the Manifest.txt file just contains these three lines:

   Manifest-Version: 1.0
   Created-By: <Your info>
   Main-Class: home.Source

However when I try to execute the jar file with:

#!/usr/bin/env bash
java -jar MyJar.jar 

I get this error:

Error: Could not find or load main class home.Source

I have no idea what to do now. Anybody know what's wrong? Perhaps I am using the wrong command to generate the .jar file?

As a check, I run jar tf :

bash-3.2$ jar tf MyJar.jar
META-INF/
META-INF/MANIFEST.MF
Other.class
Source.class

The issue is that your classes are in a package, and in the jar file should be within a directory - this is encoded in the error message: note the "class home.Source" - java will look for the Source class in a directory called home, whether a native directory or a directory in a jar (all of which must be on the classpath - the contents of an executable jar are automatically added).

When using javac it is recommended to specify a target output directory with the -d flag as doing so will create the directory structure for any packages that classes are in.

eg:

javac -d bin/ $(dirname "$0")/*.java
jar cmf MyJar.jar Manifest.txt -C bin/ *

the -C flag changes directory to the bin/ directory which contains your output package structure, and the * includes everything (you could, of course, use home/*.class here or anything else which will return the full relative path from the new CWD to the target class files).

Alternatively, you could move the classes to the relevant directories yourself, or compile them there, but it's generally better to let javac do it based on the package declaration in the source.

Finally, consider using gradle, maven or even ant to build your projects as they are all designed to avoid this kind of problem.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM