2017-11-24 8 views
0

リフレクションを使用して外部の.jar内のメソッドを呼び出す必要があります。リフレクションを使用して外部jar内のメソッドを呼び出す方法

これは、jarファイル内のサンプルコードです。

public class HelloFunction implements Runnable, RequestHandler<Request> { 

    @Override 
    public void handle(final Request request) { 
     System.out.println("handle : " + request); 
    } 

    @Override 
    public void run() { 
     System.out.println("run......"); 
    } 
} 

私は別のJavaプログラムにこのjarをロードし、HelloFunction.handle()メソッドを呼び出そうとしました。これはその部分のサンプルコードです。

public class App { 

    public static void main(String[] args) { 
     test(); 
    } 

    public static void test(){ 

     try{ 

      final Class<?> functionClass = getClassFromFunctionJar("com.hello.HelloFunction"); 

      final Object functionClassObject = functionClass.newInstance(); 

      if(functionClassObject instanceof RequestHandler){ 

       @SuppressWarnings("unchecked") 
       final RequestHandler<Object> handler = RequestHandler.class.cast(functionClassObject); 

       final Object inputObject = getRequestClass(functionClass).newInstance(); 

       handler.handle(inputObject); 


      } 

     }catch(final Exception e){ 

      System.err.println(e.getMessage()); 

     } 
    } 

    public static Class<?> getRequestClass(final Class<?> cls) throws FunctionInvokerException{ 

     try{ 
      final Type[] types = cls.getGenericInterfaces(); 

      for(Type type : types){ 

       //check RequestHandler 
       if(type.getTypeName().contains(RequestHandler.class.getName())){ 

        final ParameterizedType parameterizedType = (ParameterizedType) type; 

        // [0]=> Request Type 
        final String inputClassName = parameterizedType.getActualTypeArguments()[0].getTypeName(); 
        return getClassFromFunctionJar(inputClassName); 

       } 

      } 

      throw new Exception("UNABLE_TO_FIND_REQUEST_TYPE"); 

     }catch(final Exception e){ 
      throw new FunctionInvokerException(e); 
     } 

    } 

    private static Class<?> getClassFromFunctionJar(final String className) throws ClassNotFoundException, MalformedURLException{ 
     final ClassLoader classLoader = URLClassLoader.newInstance(new URL[]{new URL("file:" + "/jar-location/hello.jar")}, App.class.getClassLoader()); 
     return Class.forName(className, true, classLoader); 
    } 

} 

ここでは、getClassFromFunctionJar()メソッドを使用して、クラスからクラスをロードしています。また、getRequestClass()メソッドは、HelloFunction.handle()メソッドの入力パラメータのクラス型を検索するために使用されます。 handle()メソッドを呼び出すまでは問題ありません。

最後に、「com.hello.Requestをcom.hello.Requestにキャストできません」というエラーが表示されました。この問題を解決するために私を助けてください。

+0

理由を行います

実際のエラーが

"のURLClassLoader#2 com.hello.RequestがURLClassLoaderの#1 com.hello.Requestにキャストすることはできません" と、これはお勧めですあなたは反射が必要ですか? – Stultuske

+0

'com.hello.Requestはcom.hello.Request'にキャストできません。常に、2つの異なるクラスローダーを通してクラスを2回ロードしたことを意味します。既にハードコードされた参照のためにクラスが静的にロードされていて、実装をロードしたときに2番目のコピーがロードされています。これは答えとして投稿されていないのですが、エラーが出ている理由を教えてもらえますが、修正方法を教える情報が不足しています(クラスローダーの専門知識が古くなっています)。 –

+0

はい。問題は、クラスローダーtwiseをロードして、今修正しました。ありがとうございました。 – Tharanga

答えて

1

異なるクラスローダーによってロードされる同じクラス定義は、JVMによって2つの異なるクラスとして認識されます。

あなたのコード "URLClassLoader.newInstance" 異なるクラスローダ

最初(ハンドラ#パラメータ)を取得しながら、は、次のとおりです。URLClassLoaderの#1 & com.hello.Request

(はInputObject)第二は、次のとおりです。URLClassLoaderの#2 & com.hello.Request

"com.hello.Requestはcom.hello.Requestにキャストできません"。

private static final ClassLoader classLoader = URLClassLoader.newInstance(new URL[]{new URL("file:" + "/jar-location/hello.jar")}, App.class.getClassLoader()); 

private static Class<?> getClassFromFunctionJar(final String className) throws ClassNotFoundException, MalformedURLException{ 
    return Class.forName(className, true, classLoader); 
} 
+0

あなたの答えは大変ありがとうございます。今修正しました。 – Tharanga

関連する問題