用额外的类path选项调用“java -jar MyFile.jar”
我创build了一个包含我所有编译的东西的jar文件。 此外,我的ant构build脚本将所需的库复制到子文件夹“库”。 结构如下所示:
MyProgram.jar libs/
所以当我尝试运行我的程序时,我得到以下错误:
java -cp ".:/home/user/java/MyProgram/jar/libs" -jar MyProgram.jar java.lang.ClassNotFoundException: org.postgresql.Driver at java.net.URLClassLoader$1.run(URLClassLoader.java:217) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:205) at java.lang.ClassLoader.loadClass(ClassLoader.java:321) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:294) at java.lang.ClassLoader.loadClass(ClassLoader.java:266) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:186) at database.PostgresQL.getConnection(PostgresQL.java:38) at recommender.dao.Creative2IdxDAO.createCreatives2Idx(Creative2IdxDAO.java:19) at main.Main.calculateCorrelationMatrix(Main.java:51) at main.Main.main(Main.java:28) java.lang.NullPointerException at recommender.dao.Creative2IdxDAO.createCreatives2Idx(Creative2IdxDAO.java:25) at main.Main.calculateCorrelationMatrix(Main.java:51) at main.Main.main(Main.java:28)
为什么会发生?
你使用-jar
或 -cp
,你不能把两者结合起来。 如果你想在类path上添加额外的JAR,那么你应该把它们放在主JAR的清单中,然后使用java -jar
或者将完整的类path(包括主JAR及其依赖项)放在-cp
并命名主类明确地在命令行上
java -cp 'MyProgram.jar:libs/*' main.Main
(我使用的dir/*
语法告诉java
命令将所有的.jar
文件从一个特定的目录添加到类path中。注意, *
必须被shell保护以防止扩展,这就是为什么我使用single引号)。
你提到你使用Ant来替代清单方法,你可以在复制依赖关系之后 ,但是在构buildJAR 之前使用ant的<manifestclasspath>
任务。
<manifestclasspath property="myprogram.manifest.classpath" jarfile="MyProgram.jar"> <classpath> <fileset dir="libs" includes="*.jar" /> </classpath> </manifestclasspath> <jar destfile="MyProgram.jar" basedir="classes"> <manifest> <attribute name="Main-Class" value="main.Main" /> <attribute name="Class-Path" value="${myprogram.manifest.classpath}" /> </manifest> </jar>
有了这个, java -jar MyProgram.jar
将能够正常工作,并且将在类path中包含所有的libs
JAR文件。
当使用-jar选项时,-cp选项被忽略。 设置类path的唯一方法是使用jar中的清单文件。
使用-cp选项比较容易,将jar文件添加到该选项,然后显式调用主类。
另外,假设/ home / user / java / MyProgram / jar / libs文件夹包含jar文件(而不是类文件),这将不起作用。 你不能指定一个jar文件的文件夹,但是必须在类path中分别指定每个jar文件(如果有大量的jar文件,就要写一个简单的shell脚本来为你做这个)。
这有点棘手。 以下脚本试图从jar清单中获取类path,然后允许添加额外的类path条目。 我对这个有不同的结果,但是想要分享这个脚本,所以可以在这里完成function。
脚本有两个名字
- showmanifest
- calljar
将这两个文件连接在一起
ln calljar showmanifest
用calljar -h你可以看到用法。
#!/bin/bash #set -x # show the manifest of a jar file # 2012-07-18 # author WF # # show usage # usage() { echo "usage: showmanifest (jarfile | directory jarfile) " 1>&2 echo "usage: calljar directory jarfile classpath pattern arguments" 1>&2 echo " -h|--help " 1>&2 echo " show this help and exit" 1>&2 echo " -m|--mainclass javaclass" 1>&2 echo " mainclass to use (otherwise manifest is inspected)" 1>&2 exit 1 } # # show the manifest of the given jar file # show() { dir="$1" jar="$2" fulljar=`find "$dir" -name "$jar"` cd /tmp mkdir show$$ cd show$$ jar xvf $fulljar META-INF/MANIFEST.MF cat META-INF/MANIFEST.MF cd /tmp rm -rf show$$ } # # show the classpath of the manifest # calljar() { dir="$1" jar="$2" classpath="$3" pattern="$4" arguments="$5" cmd=`show "$dir" "$jar" | awk -v extracp="$classpath" -v dir="$dir" -v pattern="$pattern" -v jar="$jar" -v mainclass="$mainclass" -v args="$arguments" ' /Main-Class: / { if (mainclass=="") mainclass=$2 } /^Class-Path:/ { incp=1; cp=$0; gsub("Class-Path: ","",cp) next } /^ .*$/ && incp { line=substr($0,2) # remove carriage return (if any) cp=cp line } END { # we do not like carriage returns gsub("\\r","",cp) gsub("\\r","",mainclass) # we do not like blanks ... gsub(" ","",cp) gsub(pattern,":"dir"/"pattern,cp) print "java -cp " extracp cp ":"dir"/"jar " " mainclass " " args } '` #echo $cmd $cmd } # echo $# arguments found: $* # parse command line options while true; do # echo "option $1" case "$1" in # options without arguments -h|--help) usage;; # for options with required arguments, an additional shift is required -m|--mainclass) mainclass=$2; shift;; (--) shift; break;; (-*) echo "$0: error - unrecognized option $1" 1>&2; usage;; (*) dir=$1;shift;break;; esac shift done #echo "argcount=$#" case $# in 0) dir=`dirname "$dir"` jar=`basename "$dir"` show "$dir" "$jar";; 1) jar="$1" show "$dir" "$jar";; 2) usage;; 3) usage;; *) jar="$1"; shift; classpath="$1"; shift; pattern="$1"; shift; arguments="$@"; #echo "mainclass=${mainclass}" #echo "classpath=${classpath}" #echo calljar "${dir}" "${jar}" "${classpath}" "$pattern" "$arguments" calljar "$dir" "$jar" "$classpath" "$pattern" "$arguments" ;; esac
对于应用程序的快速一次性testing,您可以简单地将所需的依赖项JAR文件符号链接到包含主应用程序JAR文件的目录中。
示例(对于使用Eclipse SWT库(在我的情况下安装在/usr/share/java
的应用程序app.jar
):
$ ln -s /usr/share/java/swt.jar . $ java -jar app.jar