अतिरिक्त क्लासपाथ विकल्प के साथ "जावा-मज़ार MyFile.jar" को कॉल करें


91

मैंने एक जार फ़ाइल बनाई जिसमें मेरा सारा संकलित सामान था। इसके अतिरिक्त मेरी चींटी का निर्माण स्क्रिप्ट आवश्यक कामों को एक सबफ़ोल्डर "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)

क्यों होता है ऐसा?

जवाबों:


151

आप या तो उपयोग करते हैं , -jar या -cp आप दोनों को जोड़ नहीं सकते। अगर आप क्लासपैथ पर अतिरिक्त JAR लगाना चाहते हैं तो आपको या तो उन्हें मुख्य JAR की मेनिफ़ेस्ट में डालना चाहिए और फिर java -jarपूरा क्लासपाथ (मुख्य JAR और उसकी निर्भरता सहित) डालना चाहिए -cpऔर कमांड लाइन पर मुख्य क्लास को स्पष्ट रूप से नाम देना चाहिए।

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

(मैं dir/*वाक्य रचना का उपयोग कर रहा हूं जो किसी विशेष निर्देशिका से क्लासपाथ में javaसभी .jarफ़ाइलों को जोड़ने के लिए कमांड को बताता है । ध्यान दें कि *शेल द्वारा विस्तार से संरक्षित किया जाना चाहिए, यही कारण है कि मैंने एकल उद्धरण का उपयोग किया है।)

आप उल्लेख करते हैं कि आप ऐंटी का उपयोग कर रहे हैं वैकल्पिक प्रकटन दृष्टिकोण के लिए, आप निर्भरता की प्रतिलिपि बनाने के बाद चींटी के <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 फ़ाइलों को भी शामिल करेगा ।


ऊपर जोड़, या MANIFEST.MF फ़ाइल में आवश्यक जार प्रविष्टियों को जोड़ने के बारे में सोचें।
हिमांशु भारद्वाज

@ हिमांशु भारद्वाज वास्तव में, मैंने इसका उपयोग करने का एक उदाहरण जोड़ा है<manifestclasspath>
इयान रॉबर्ट्स

व्हाट्स अप 'मायप्रोग्राम.जर: लिबास / * ’में यह है?
गोबलींस

@Gobliins कोलोन लिनक्स और मैक ऑपरेटिंग सिस्टम के तहत पथ के बीच विभाजक है। विंडोज पर आप सेमीकॉलन ( ;) का उपयोग करेंगे बजाय विंडोज पर कोलन ड्राइव अक्षर के लिए उपयोग किया जाता है। ओपी ने अपने प्रश्न में कॉलन और फॉरवर्ड स्लैश का उपयोग किया, यह सुझाव दिया कि वे लिनक्स या मैक पर हैं।
इयान रॉबर्ट्स

5
यदि विकल्प परस्पर अनन्य हैं, तो कमांड लाइन को एक चेतावनी प्रिंट करना चाहिए जब दोनों का उपयोग किया जाता है। इस सामान्य ज्ञान के लिए समय कौन है ?!
JJS

22

जब -jarविकल्प का उपयोग किया जाता है तो -cpविकल्प को नजरअंदाज कर दिया जाता है। क्लासपैथ सेट करने का एकमात्र तरीका जार में प्रकट फ़ाइल का उपयोग करना है।

केवल -cpविकल्प का उपयोग करना आसान है , अपनी जार फ़ाइल को उसमें जोड़ें, फिर स्पष्ट रूप से मुख्य वर्ग को कॉल करें।

इसके अलावा, /home/user/java/MyProgram/jar/libsफ़ोल्डर को संभालने में जार फाइलें शामिल हैं (वर्ग फ़ाइलों के विपरीत) यह काम नहीं करेगा। आप जार फ़ाइल का एक फ़ोल्डर निर्दिष्ट नहीं कर सकते हैं, लेकिन प्रत्येक जार फ़ाइल को व्यक्तिगत रूप से classpath में निर्दिष्ट करना चाहिए (यह आपके लिए यह करने के लिए एक सरल शेल स्क्रिप्ट लिखने के लायक है यदि आपके पास जार की एक महत्वपूर्ण संख्या है)।


0

यह थोड़ा मुश्किल है। निम्न स्क्रिप्ट जार के प्रकट होने से क्लासपाथ प्राप्त करने का प्रयास है और फिर अतिरिक्त क्लासपैथ प्रविष्टियों को जोड़ने की अनुमति देता है। मेरे पास इसके साथ मिश्रित परिणाम थे, लेकिन स्क्रिप्ट को फिर भी साझा करना चाहते हैं, इसलिए इसे यहां पूरी तरह कार्यात्मक बनाया जा सकता है।

स्क्रिप्ट के दो नाम हैं

  • 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

-1

किसी एप्लिकेशन के त्वरित, एक-बंद परीक्षणों के लिए, आप केवल मुख्य ऐप जार फ़ाइल वाले निर्देशिका में आवश्यक निर्भरता JAR फ़ाइलों को सिम्लिंक कर सकते हैं।

उदाहरण (एक ऐप app.jarजो ग्रहण एसडब्ल्यूटी पुस्तकालय का उपयोग करता है, जो मेरे मामले में स्थापित किया गया था /usr/share/java):

$ ln -s /usr/share/java/swt.jar .
$ java -jar app.jar
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.