2017-03-18 6 views
1

私は、次の2つのクラスを含むjarファイルfoobar.jarを持っている:Javaクラスは、クラスパスに存在するが、起動がエラーで失敗します。メインクラスを見つけるか、ロードできませんでした

public class Foo { 

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

他のクラスには、次のようになります。

​​

私は、次のコマンドを使用してプログラムを実行すると予想されるように、プログラムの動作やプリントFoo

$ java -cp foobar.jar Foo 
Foo 
$ 

しかし、私はクラスBarでmainメソッドを使用してプログラムを起動しようとした場合、JVMは起動エラーを出力して終了します:

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

これは私がプログラムを起動しようとするかのように同じエラーですjarファイルにないクラスを使用します。

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

なぜこのエラーが発生しますか? Foo.mainメソッドを起動でき、jarからクラスBarを逆コンパイルすることができるという事実は、クラスがクラスパス上で利用可能であることを証明します。私はこのことがクラスパス上にないインターフェイスItemProcessorと関係があることを理解しています。しかし、その場合に私はjava.lang.ClassNotFoundExceptionを受け取るべきではありませんか?

+0

この問題は、部分的にhttp://stackoverflow.com/questions/18093928/what-does-could-not-find-or-load-main-class-meanで覆われていることに注意してください。私はこの問題に遭遇し、上記の質問を使用して解決しようとしました。しかし、クラスパス上にないスーパークラスの問題は一種のエッジケースなので、最初は解決できませんでした。これが新しいQ/Aとしてこの特定のケースを追加した理由です。 – boskoop

答えて

4

実際には、インターフェイスItemProcessorがクラスパス上にないという問題があります。エラーが「またはロードメインクラス」を検索することを確認します。 BarNotThereの場合、JVMは実際にを見つけることができません。をメインクラスとしています。しかし、Barの場合、ロードをメインクラスとすることはできません。

クラスを完全にロードするために、JVMは各スーパークラスオブジェクトのインスタンスも必要とします。 Barのこの処理中に、JVMはItemProcessorのクラスオブジェクトをロードしようとします。しかし、このインタフェースはクラスパス上にないので、メインクラスBarのロードは失敗し、起動はError: Could not find or load main class Barで終了します。


さらに説明

ローディングとクラスの初期化の間の差に注目してください。初期化中にクラスロードが失敗した場合(クラスが正常にに見つかり、およびにロードされた場合)、ClassNotFoundExceptionが得られます。次の例を参照してください。この場合

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"); 
    } 
} 

を、クラスFooBarは、起動時にロードすることができます。しかし、静的フィールドiはクラスパス上にないItemProcessorクラスを必要とするため、初期化することはできません。 JVMがmainメソッドを呼び出そうとしたときに、クラスの静的メソッドが実行される場合、初期化は前提条件です。

$ 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 
$ 
関連する問題