developer tip

추가 클래스 경로 옵션을 사용하여 "java -jar MyFile.jar"호출

optionbox 2020. 10. 12. 07:28
반응형

추가 클래스 경로 옵션을 사용하여 "java -jar MyFile.jar"호출


모든 컴파일 된 내용을 포함하는 jar 파일을 만들었습니다. 또한 내 ant 빌드 스크립트는 필요한 libs를 하위 폴더 "libs"에 복사합니다. 구조는 다음과 같습니다.

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 당신은 두 가지를 결합 할 수 없습니다. 추가 JAR을 클래스 경로에 넣으려면 기본 JAR의 매니페스트에 넣은 다음 사용 java -jar하거나 전체 클래스 경로 (기본 JAR 및 해당 종속성 포함)를 입력 -cp하고 명령 줄에서 명시 적으로 기본 클래스의 이름을 지정해야합니다.

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

(저는 특정 디렉터리의 모든 파일을 클래스 경로 에 추가 dir/*하도록 java명령에 지시 하는 구문을 사용하고 있습니다 .jar. *은 셸에 의한 확장으로부터 보호되어야하므로 작은 따옴표를 사용했습니다.)

Ant를 사용하고 있으므로 대체 매니페스트 접근 방식으로 종속성 복사 한 JAR을 빌드 하기 전에 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올바르게 작동 libs하며 클래스 경로의 모든 JAR 파일도 포함됩니다.


-jar옵션이 사용되는 -cp옵션은 무시됩니다. 클래스 경로를 설정하는 유일한 방법은 jar의 매니페스트 파일을 사용하는 것입니다.

-cp옵션을 사용하고 여기에 jar 파일을 추가 한 다음 명시 적으로 기본 클래스를 호출하는 것이 더 쉽습니다 .

또한 /home/user/java/MyProgram/jar/libs폴더에 jar 파일이 포함되어 있다고 가정하면 (클래스 파일과 반대) 작동하지 않습니다. jar 파일의 폴더를 지정할 수는 없지만 클래스 경로에서 각 jar 파일을 개별적으로 지정해야합니다 (중요한 수의 jar가있는 경우이를 수행하기 위해 간단한 쉘 스크립트를 작성하는 것이 좋습니다).


약간 까다 롭습니다. 다음 스크립트는 jar의 매니페스트에서 클래스 경로를 가져온 다음 추가 클래스 경로 항목을 추가하도록 허용하는 것입니다. 나는 이것과 혼합 된 결과를 가지고 있었지만 그럼에도 불구하고 스크립트를 공유하여 여기에서 완전히 작동하도록 만들고 싶습니다.

스크립트에는 두 가지 이름이 있습니다.

  • 쇼 매니페스트
  • 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

For quick, one-off tests of an app, you can simply symlink the needed dependency JAR files into the directory containing the main app JAR file.

Example (for an app app.jar which uses the Eclipse SWT library, which in my case was installed in /usr/share/java):

$ ln -s /usr/share/java/swt.jar .
$ java -jar app.jar

참고URL : https://stackoverflow.com/questions/15930782/call-java-jar-myfile-jar-with-additional-classpath-option

반응형