2017-03-18 3 views
1

ich eine JAR-Datei finden oder laden haben foobar.jar die folgenden zwei Klassen enthalten:Java-Klasse ist in Classpath aber Start schlägt fehl mit Fehler: Konnte keine Hauptklasse

public class Foo { 

    public static void main(String[] args) { 
     System.out.println("Foo"); 
    } 
} 

Die andere Klasse sieht wie folgt aus:

import javax.batch.api.chunk.ItemProcessor; 

public class Bar implements ItemProcessor { 

    public static void main(String[] args) { 
     System.out.println("Bar"); 
    } 

    @Override 
    public Object processItem(Object item) throws Exception { 
     return item; 
    } 
} 

Wenn ich das Programm mit dem folgenden Befehl ausführen, verhält sich das Programm wie erwartet und druckt Foo:

$ java -cp foobar.jar Foo 
Foo 
$ 

Aber wenn ich das Programm zu starten mit der Haupt-Methode in der Klasse Bar, die JVM druckt einen Startfehler und tritt versuchen:

$ java -cp foobar.jar Bar 
Error: Could not find or load main class Bar 
$ 

Dies ist der gleiche Fehler wie wenn ich versuchen würde, das Programm zu starten unter Verwendung einer Klasse, die nicht im Jar ist, z

$ java -cp foobar.jar BarNotThere 
Error: Could not find or load main class BarNotThere 
$ 

Warum bekomme ich diesen Fehler? Die Tatsache, dass die Foo.main Methode gestartet werden kann, und ich bin in der Lage, die Klasse Bar aus dem Glas zu dekompilieren beweist, dass die Klasse im Klassenpfad verfügbar sein sollte. Ich weiß, dass dies etwas mit der Schnittstelle ItemProcessor nicht auf dem Klassenpfad zu tun haben könnte. Aber sollte ich nicht einen java.lang.ClassNotFoundException in diesem Fall bekommen?

+0

Bitte beachten Sie, dass dieses Problem teilweise durch http://stackoverflow.com/questions/18093928/what-does-could-not-find-or-load-main-class-mean bedeckt ist. Ich bin auf dieses Problem gestoßen und habe versucht, es mit dieser Frage zu lösen. Aber zuerst konnte ich es nicht lösen, weil das Problem, dass die Oberklasse nicht auf dem Klassenpfad ist, ein Randfall ist. Deshalb habe ich diesen speziellen Fall als neues Q/A hinzugefügt. – boskoop

Antwort

4

Das Problem ist in der Tat, dass die Schnittstelle ItemProcessor nicht auf dem Classpath ist. Beachten Sie, dass die Fehlerzustände „ oder Last Hauptklasse finden“. Im Fall von BarNotThere ist die JVM wirklich nicht in der Lage, der Hauptklasse zu finden. Aber im Bar Fall ist es nicht in der Lage zu Last die Hauptklasse.

Um vollständig eine Klasse zu laden, die JVM brauchen auch Instanzen der einzelnen Super Objekte. Während dieses Prozesses für Bar versucht die JVM das Klassenobjekt für ItemProcessor zu laden. Da diese Schnittstelle jedoch nicht im Klassenpfad enthalten ist, schlägt das Laden der Hauptklasse Bar fehl und der Start wird mit der Error: Could not find or load main class Bar beendet.


Weitere Erläuterungen

Beachten Sie den Unterschied zwischen Laden und eine Klasse zu initialisieren. Wenn Classloading bei der Initialisierung fehlschlägt (was bedeutet, dass die Klasse war erfolgreich gefunden und geladen), werden Sie Ihre erwartete ClassNotFoundException bekommen. Siehe das folgende Beispiel:

import javax.batch.api.chunk.ItemProcessor; 

public class FooBar { 

    private static ItemProcessor i = new ItemProcessor() { 
     @Override 
     public Object processItem(Object item) throws Exception { 
      return item; 
     } 
    }; 

    public static void main(String[] args) { 
     System.out.println("Foo"); 
    } 
} 

In diesem Fall wird die Klasse FooBar kann während des Startvorgangs geladen werden. Es kann jedoch nicht initialisiert werden, da das statische Feld i die Klasse ItemProcessor benötigt, die nicht im Klassenpfad enthalten ist. Die Initialisierung ist eine Voraussetzung, wenn eine statische Methode für eine Klasse ausgeführt wird. Dies ist der Fall, wenn die JVM versucht, die Methode main aufzurufen.

$ java -cp foobar.jar FooBar 
Error: A JNI error has occurred, please check your installation and try again 
Exception in thread "main" java.lang.NoClassDefFoundError: javax/batch/api/chunk/ItemProcessor 
     at java.lang.Class.getDeclaredMethods0(Native Method) 
     at java.lang.Class.privateGetDeclaredMethods(Class.java:2701) 
     at java.lang.Class.privateGetMethodRecursive(Class.java:3048) 
     at java.lang.Class.getMethod0(Class.java:3018) 
     at java.lang.Class.getMethod(Class.java:1784) 
     at sun.launcher.LauncherHelper.validateMainClass(LauncherHelper.java:544) 
     at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:526) 
Caused by: java.lang.ClassNotFoundException: javax.batch.api.chunk.ItemProcessor 
     at java.net.URLClassLoader.findClass(URLClassLoader.java:381) 
     at java.lang.ClassLoader.loadClass(ClassLoader.java:424) 
     at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331) 
     at java.lang.ClassLoader.loadClass(ClassLoader.java:357) 
     ... 7 more 
$ 
Verwandte Themen