Utworzyłem plik jar zawierający wszystkie moje skompilowane rzeczy. Dodatkowo mój skrypt kompilacji Ant kopiuje wymagane biblioteki do podfolderu „libs”. Struktura wygląda następująco:
MyProgram.jar
libs/
Kiedy próbuję teraz uruchomić program, pojawia się następujący błąd:
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)
Dlaczego to się dzieje?
<manifestclasspath>
;
) zamiast dwukropka w systemie Windows do liter dysków. OP użył dwukropków i ukośników w swoim pytaniu, sugerując, że są na Linuksie lub Macu.Gdy ta
-jar
opcja jest używana-cp
, jest ona ignorowana. Jedynym sposobem ustawienia ścieżki klas jest użycie pliku manifestu w jar.Łatwiej jest po prostu użyć tej
-cp
opcji, dodać do tego plik jar, a następnie jawnie wywołać klasę główną.Ponadto zakładając, że
/home/user/java/MyProgram/jar/libs
folder zawiera pliki jar (w przeciwieństwie do plików klas), to nie zadziała. Nie możesz określić folderu pliku jar, ale musisz określić każdy plik jar indywidualnie w ścieżce klas (warto napisać prosty skrypt powłoki, który zrobi to za Ciebie, jeśli istnieje znaczna liczba plików jar).źródło
To trochę skomplikowane. Poniższy skrypt jest próbą pobrania ścieżki klas z manifestu pliku jar, a następnie pozwala na dodanie dodatkowych wpisów ścieżki klas. Miałem mieszane wyniki, ale mimo to chcę udostępnić skrypt, aby mógł być tutaj w pełni funkcjonalny.
Skrypt ma dwie nazwy
łącząc dwa pliki razem z
z calljar -h możesz zobaczyć użycie.
#!/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
źródło
Aby szybko i jednorazowo przetestować aplikację, możesz po prostu dowiązać symbolicznie potrzebne pliki JAR zależności do katalogu zawierającego plik JAR głównej aplikacji.
Przykład (dla aplikacji
app.jar
korzystającej z biblioteki Eclipse SWT, w której w moim przypadku była zainstalowana/usr/share/java
):źródło