जार से एक क्लास कैसे चलाया जाए जो उसकी मेनिफेस्ट फाइल में मेन-क्लास नहीं है


166

मेरे पास 4 वर्गों के साथ एक जार है, प्रत्येक में मुख्य विधि है। मैं जरूरत के अनुसार उनमें से हर एक को चलाने में सक्षम होना चाहता हूं। मैं इसे लिनक्स बॉक्स पर कमांड-लाइन से चलाने की कोशिश कर रहा हूं।

E.g. The name of my JAR is MyJar.jar

इसमें मुख्य वर्गों के लिए निर्देशिका संरचना निम्नानुसार है:

com/mycomp/myproj/dir1/MainClass1.class
com/mycomp/myproj/dir2/MainClass2.class
com/mycomp/myproj/dir3/MainClass3.class
com/mycomp/myproj/dir4/MainClass4.class

मुझे पता है कि मैं अपनी मैनिफ़ेस्ट फ़ाइल में मुख्य रूप से एक वर्ग निर्दिष्ट कर सकता हूं। लेकिन क्या कोई ऐसा तरीका है जिसके द्वारा मैं कमांड लाइन पर कुछ तर्क निर्दिष्ट कर सकता हूं जिसे मैं चलाने की इच्छा रखता हूं?

मैंने यह कोशिश की:

jar cfe MyJar.jar com.mycomp.myproj.dir2.MainClass2 com/mycomp/myproj/dir2/MainClass2.class /home/myhome/datasource.properties /home/myhome/input.txt

और मुझे यह त्रुटि मिली:

com/mycomp/myproj/dir2/MainClass2.class : no such file or directory

(उपरोक्त कमांड में, '/home/myhome/datasource.properties' और '/home/myhome/input.txt' कमांड लाइन तर्क हैं)।


बस उन्हें अलग-अलग जार में पैकेज करें, निर्भरता रखने के लिए दूसरे जार का उपयोग करें?
निक

11
कमांड लाइन के तर्कों के आधार पर विशिष्ट विधि (4 में से) को कॉल करने वाला एकल मुख्य वर्ग क्यों नहीं है?
को नहीं बता सकते

जवाबों:


215

आप अपने घोषणापत्र फ़ाइल में मेन-क्लास के बिना अपना जार बना सकते हैं। फिर :

java -cp MyJar.jar com.mycomp.myproj.dir2.MainClass2 /home/myhome/datasource.properties /home/myhome/input.txt

2
डॉक्टर के अनुसार यह काम नहीं करेगा: "काम करने के लिए इस विकल्प के लिए, JAR फ़ाइल के प्रकट होने में मेन-क्लास: क्लासनाम के रूप की एक पंक्ति होनी चाहिए।"
थॉमस

"MyJar.jar से मुख्य-वर्ग की प्रकट विशेषता को लोड करने में विफल"
भूषण

10
थॉमस सही है। आपको "-cp" के साथ "-jar" को बदलने की आवश्यकता है। मेरा अद्यतन कोड देखें
lxu4net

9
@Chrisdew द्वारा प्रदान किया गया उत्तर मेन-क्लास विशेषता को संशोधित / हटाकर जार फ़ाइल को बदलने के बिना काम करता है।
एड ग्रिबेल

155

आप किसी भी वर्ग को निष्पादित कर सकते हैं जिसमें public final static mainएक JAR फ़ाइल से एक विधि है, भले ही जार फ़ाइल में एक Main-Classपरिभाषित हो

निष्पादित मुख्य-वर्ग:

java -jar MyJar.jar  // will execute the Main-Class

किसी अन्य वर्ग को public static void mainविधि से निष्पादित करें :

java -cp MyJar.jar com.mycomp.myproj.AnotherClassWithMainMethod

नोट: पहला उपयोग करता है -jar, दूसरा उपयोग करता है -cp


10
और यदि आप classpath पर भी वर्तमान निर्देशिका में सभी जार चाहते हैं (जैसे कि lib निर्देशिका से मुख्य वर्ग चल रहा है) तो आप यूनिक्स मशीनों को इसे विस्तारित करने से रोकने के java -cp "./*" com.mycomp.myproj.AnotherClassWithMainMethodआसपास दोहरे उद्धरण चिह्नों का उपयोग कर सकते हैं ./*। यह भी ध्यान दें कि "./*.jar"काम नहीं करेगा।
पेट्र Petजदस्क़ी

19

कॉलिंग के अलावा java -jar myjar.jar com.mycompany.Myclass, आप अपने मेनिफेस्ट को डिस्पैचर क्लास में भी मुख्य वर्ग बना सकते हैं।

उदाहरण:

public class Dispatcher{

    private static final Map<String, Class<?>> ENTRY_POINTS =
        new HashMap<String, Class<?>>();
    static{
        ENTRY_POINTS.put("foo", Foo.class);
        ENTRY_POINTS.put("bar", Bar.class);
        ENTRY_POINTS.put("baz", Baz.class);
    }

    public static void main(final String[] args) throws Exception{

        if(args.length < 1){
            // throw exception, not enough args
        }
        final Class<?> entryPoint = ENTRY_POINTS.get(args[0]);
        if(entryPoint==null){
            // throw exception, entry point doesn't exist
        }
        final String[] argsCopy =
            args.length > 1
                ? Arrays.copyOfRange(args, 1, args.length)
                : new String[0];
        entryPoint.getMethod("main", String[].class).invoke(null,
            (Object) argsCopy);

    }
}

1
यह एक अच्छा वैकल्पिक तरीका है! मेरा जार "स्प्रिंग-बूट: रीपैकेज" का उपयोग करके बनाया गया था, इसलिए मैं अन्य प्रवेश कक्षाओं को "-सीपी" तरीके से नहीं चला सकता। मुझे नहीं पता कि वसंत-बूट प्लगइन ने जार को क्या किया। इस मामले में, एक प्रेषण वर्ग मदद करता है।
झोउ

6

यह उत्तर स्प्रिंग-बूट उपयोगकर्ताओं के लिए है:

यदि आपका JAR एक Spring-bootप्रोजेक्ट से था और कमांड का उपयोग करके बनाया गया था mvn package spring-boot:repackage, तो उपरोक्त "-cp" विधि काम नहीं करेगी। तुम्हे मिल जाएगा:

त्रुटि: मुख्य वर्ग your.alternative.class.path को ढूंढ या लोड नहीं कर सका

यहां तक ​​कि अगर आप कक्षा को जार में देख सकते हैं jar tvf yours.jar

इस स्थिति में, निम्न आदेश द्वारा अपना वैकल्पिक वर्ग चलाएं:

java -cp yours.jar -Dloader.main=your.alternative.class.path org.springframework.boot.loader.PropertiesLauncher

जैसा कि मैंने समझा, स्प्रिंग-बूट की org.springframework.boot.loader.PropertiesLauncherकक्षा एक प्रेषण प्रवेश द्वार के रूप में कार्य करती है, और -Dloader.mainपैरामीटर इसे बताता है कि क्या चलाना है।

संदर्भ: https://github.com/spring-projects/spring-boot/issues/20404


क्या होगा अगर आपका जार निष्पादन योग्य है। यानी जब आप जार को अनज़िप करते हैं, तो सभी कक्षाएं "/ BOOT-INF / classes /" से पहले होती हैं
slashdottir

2

सबसे पहले jarएक जार बनाता है, और इसे नहीं चलाता है। java -jarइसके बजाय कोशिश करें ।

दूसरा, आप FQCN ( com.mycomp.myproj.dir2.MainClass2) और फ़ाइल ( com/mycomp/myproj/dir2/MainClass2.class) के रूप में दो बार कक्षा क्यों पास करते हैं ?

संपादित करें:

ऐसा लगता है जैसे java -jarएक मुख्य वर्ग को निर्दिष्ट करने की आवश्यकता है। आप java -cp your.jar com.mycomp.myproj.dir2.MainClass2 ...इसके बजाय कोशिश कर सकते हैं । -cpवर्गपथ पर जार सेट करता है और जावा को वहां के मुख्य वर्ग को देखने में सक्षम बनाता है।


जैसा कि मैंने यहाँ बताया है: download.oracle.com/javase/tutorial/deployment/jar/appman.html
भूषण

1
उस पृष्ठ से: "इसका उपयोग जार फ़ाइल बनाते या अद्यतन करते समय किया जा सकता है।" - तो यह मुख्य वर्ग विशेषता सेट करने के लिए उपयोग किया जाता है, जार को चलाने के लिए नहीं।
थॉमस

1

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

MyJar 1 .jar \ META-INF \ MANIFEST.MF

Manifest-Version: 1.0
Main-Class: com.mycomp.myproj.dir1.MainClass1
Class-Path: MyJar.jar

MyJar 2 .jar \ META-INF \ MANIFEST.MF

Manifest-Version: 1.0
Main-Class: com.mycomp.myproj.dir2.MainClass2
Class-Path: MyJar.jar

आदि तो बस इसे चलाने के साथ java -jar MyJar2.jar


-4

अपनी pom.xml फ़ाइल में नीचे प्लगइन जोड़ें और तत्व में पूरी तरह से योग्य नाम के साथ मुख्य वर्ग निर्दिष्ट करें।

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <version>1.2.5.RELEASE</version>
    <configuration>
        <mainClass>**main Class name with full qualified name**</mainClass>
    </configuration>
    <executions>
        <execution>
            <goals>
                <goal>repackage</goal>
            </goals>
        </execution>
    </executions>
</plugin>
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.