2017-05-19 31 views
0

jarファイルからクラスを読み込もうとしています。基本的には、そのjarファイルのパッケージ内の特定のクラスのメソッドを呼び出す必要があります。私がここで直面している問題は、クラスが正常にjarからロードされた後、インスタンス化しようとすると例外が発生するということです。クラスにインポートされたクラスのClassNotFoundです。ここJavaでリフレクションを使用して読み込んだクラスの読み込みクラスの読み込み

は、クラスをロードするクラスである:

入力:D:\ Myjar.jar、com.vendor.epbroker.VNFLCMCommunicator

public Class<?> loadClass(String libPath, String pkgName) { 
     LogManager.getLogger().info("Adding Class"); 

     File jarFile = null; 
     try { 
      jarFile = new File(libPath); 
      URL fileURL = jarFile.toURI().toURL(); 
      String jarURL = "jar:" + fileURL + "!/"; 
      URL urls[] = { new URL(jarURL) }; 
      URLClassLoader ucl = new URLClassLoader(urls); 
      Class<?> beanClass = ucl.loadClass(pkgName); 
      ucl.close(); 

      return beanClass; 
     } catch (Exception ex) { 
      LogManager.getLogger().error("Given Library: " + libPath + " or Class name: " + pkgName + " is not Valid"); 
      LogManager.getLogger().error("Exception occurred : ", ex); 
     } 

     LogManager.getLogger().error("Class loading Error: Returning NULL"); 
     return null; 
    } 

このクラスを受け取るコードスニペット:

Object instance = classToLoad.newInstance(); 

       // To get the list of methods exist in the Class 
Method[] listOfMethods = classToLoad.getMethods(); 

次のエラーが発生します。

SEVERE: Servlet.service() for servlet [spring] in context with path [/vnflcm] threw exception [Handler processing failed; nested exception is java.lang.NoClassDefFoundError: com/vendor/epbroker/exception/EPBrokerException] with root cause 
java.lang.ClassNotFoundException: com.vendor.epbroker.exception.EPBrokerException 
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381) 
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424) 
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357) 
    at java.lang.Class.getDeclaredConstructors0(Native Method) 
    at java.lang.Class.privateGetDeclaredConstructors(Class.java:2671) 
    at java.lang.Class.getConstructor0(Class.java:3075) 

何か助けていただければ幸いですか?

+0

'String jarURL = ...'行を削除してください。 URLは「jar:」URLであってはなりません。ただ 'URL urls [] = {fileURL};'を実行してください。 – VGR

+0

@VGRこれも役に立たなかった。これを実行しても同じエラーが発生しました。また、エラーはcom.google.gson.Gsonと他のパッケージのクラスでも発生していました。これを解決する方法がわかりません。 –

+0

com.google.gson.Gsonを読み込もうとしたときにエラーが発生しましたが、com.vendor.epbroker.exception.EPBrokerExceptionが見つからないという例外があります。あなたの.jarファイルにEPBrokerException.classがありますか? – VGR

答えて

0

Reflectionを使用するときに考慮する必要がある点がいくつかあります。

  1. URLClassLoaderには、反映したいjarのURLが含まれている必要があります。
  2. 目的のjarが他のjarに依存する場合は、そのjarのURLもロードする必要があります。
  3. @VGRが指摘しているように、単にjarのファイルパスをURLとして使用することはできません。あなたができることの一つは、次のとおりです。

    File myJar = new File("path/to/myJar.jar"); 
    URL myJarUrl = myJar.toURI().toURL(); 
    

問題を実証するための簡単な例:

のは、あなたのjar myToolProjectを呼ぶことにしましょう。そして、あなたが作成したこのツールを開発中にJsonMakerというPOJOをJSONに変換し、gson.jarでこれを達成するクラスを作成したとします。あなたの瓶を作るとき、それをmyjar.jarと呼ぶことにしましょう。それはgsonに依存するというマニフェストに言及します。

myjarを反映させようとするとき、あなたはJsonMaker.classに達するまで、あなたのjarファイルの各クラスを反映します。ここに反映させようとすると、ここにcom.google.Gsonタイプのオブジェクトがあることがわかります。 URLClassLoaderは配列内のURLを調べ、クラスによってはcom.google.Gsonを見つけようとします。 com.google.Gsonクラスが見つからない場合は、クラスに反映されず、ClassNotFoundExceptionがスローされます。

0

は、以下の行を見ている:

URLClassLoader ucl = new URLClassLoader(urls); 
Class<?> beanClass = ucl.loadClass(pkgName); 
ucl.close(); 

をしてURLClassLoader.close()の文書化を検討:もはや新しいクラスやリソースをロードするために使用することができないように

は、このするURLClassLoaderを閉じますこのローダーによって定義されています。

つまり、実際にそのローダーのクラスを使用している場合は、クラスローダーを閉じる必要があります。この時点ですべての必須クラスがすでにロードされていたとしても、必要なリソースにアクセスする必要がある可能性がありました。いくつかのフレームワークには、クラスのバイトコードへのアクセスを必要とするリフレクションライブラリがあり、リソースのようなアクセスになります。

具体的には、さらに簡単です。 1つのクラスを読み込んだだけで、必要な最小限のクラス(たとえば直接スーパークラス)の解決がトリガされましたが、他の依存関係はありません。次に、クラスローダーを閉じ、jarファイルから他のクラスをロードするのを防ぎます。これは、コンストラクターを解決するときに参照クラスを解決する必要があります。

関連する問題