Ek sınıf yolu seçeneği ile "java -jar MyFile.jar" ı arayın


93

Tüm derlenmiş öğelerimi içeren bir jar dosyası oluşturdum. Ek olarak, karınca derleme betiğim gerekli kitaplıkları "kitaplıklar" alt klasörüne kopyalar. Yapı şuna benzer:

MyProgram.jar
libs/

Bu yüzden şimdi programımı çalıştırmayı denediğimde aşağıdaki hatayı alıyorum:

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)

Bu neden oluyor?

Yanıtlar:


153

Ya -jar veya kullanırsanız, ikisini-cp birleştiremezsiniz. Sınıf yoluna ek JAR'lar eklemek istiyorsanız, bunları ya ana JAR'ın bildirimine java -jarkoymalı ve sonra kullanmalısınız ya da tam sınıf yolunu (ana JAR ve bağımlılıkları dahil) içine koymalı -cpve ana sınıfı komut satırında açıkça adlandırmalısınız.

java -cp 'MyProgram.jar:libs/*' main.Main

( Komuta belirli bir dizinden tüm dosyaları sınıf yoluna eklemesini dir/*söyleyen sözdizimini kullanıyorum . Kabuk tarafından genişletilmeye karşı korunması gerektiğini unutmayın , bu yüzden tek tırnaklar kullandım.)java.jar*

Ant'ı kullandığınızı söylüyorsunuz, bu nedenle alternatif tezahür yaklaşımı için, bağımlılıkları kopyaladıktan sonra ancak JAR'ı oluşturmadan önce ant'ın <manifestclasspath>görevini kullanabilirsiniz .

<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>

Bu yerinde olduğunda, java -jar MyProgram.jardüzgün çalışacak libsve sınıf yolundaki tüm JAR dosyalarını da içerecektir .


Yukarıya ekleme veya gerekli jar girişlerini MANIFEST.MF dosyasına eklemeyi düşünün.
Himanshu Bhardwaj

@HimanshuBhardwaj gerçekten, ben kullanarak bunu nasıl bir örnek ekledik<manifestclasspath>
Ian Roberts

'MyProgram.jar: libs / *' içindeki ':' bu bir ayırıcı mı?
Gobliins

@Gobliins iki nokta üst üste işareti, Linux ve Mac işletim sistemlerinde bir yoldaki öğeler arasındaki ayırıcıdır. Windows'ta ;sürücü harfleri için iki nokta üst üste kullanıldığından, Windows'ta bunun yerine noktalı virgül ( ) kullanırsınız. OP sorusunda iki nokta üst üste ve eğik çizgiler kullandı ve bunların Linux veya Mac'te olduklarını öne sürdü.
Ian Roberts

5
Seçenekler birbirini dışlamıyorsa, her ikisi de kullanıldığında komut satırı bir uyarı yazdırmalıdır. Bu trivia için kimin zamanı var ?!
JJS

23

Ne zaman -jarbir seçenek kullanıldığında -cpseçenek göz ardı edilir. Sınıf yolunu ayarlamanın tek yolu kavanozdaki bildirim dosyasını kullanmaktır.

-cpSeçeneği kullanmak, jar dosyanızı buna eklemek ve ardından açıkça ana sınıfı çağırmak daha kolaydır .

Ayrıca, /home/user/java/MyProgram/jar/libsklasörün jar dosyaları içerdiğini varsayarsak (sınıf dosyalarının aksine) bu işe yaramaz. Bir jar dosyası klasörü belirtemezsiniz, ancak her bir jar dosyasını sınıf yolunda ayrı ayrı belirtmelisiniz (önemli sayıda kavanoz varsa bunu sizin için yapmak için basit bir kabuk komut dosyası yazmaya değer).


0

Biraz aldatıcı. Aşağıdaki komut dosyası, jar bildiriminden sınıf yolunu alma ve ardından fazladan sınıf yolu girişleri eklemeye izin verme girişimidir. Bununla karışık sonuçlar aldım ancak yine de senaryoyu paylaşmak istiyorum, böylece burada tamamen işlevsel hale getirilebilir.

Komut dosyasının iki adı var

  • showmanifest
  • Calljar

iki dosyayı birbirine bağlayarak

ln calljar showmanifest

calljar -h ile kullanımını görebilirsiniz.

#!/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

-1

Bir uygulamanın hızlı, tek seferlik testleri için, gerekli bağımlılık JAR dosyalarını ana uygulama JAR dosyasını içeren dizine sembolik olarak bağlayabilirsiniz.

Örnek ( app.jarbenim durumumda yüklenmiş olan Eclipse SWT kitaplığını kullanan bir uygulama için /usr/share/java):

$ ln -s /usr/share/java/swt.jar .
$ java -jar app.jar
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.