2017-11-24 5 views
0

리플렉션을 사용하여 외부 .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......"); 
    } 
} 

그런 다음이 jar를 별도의 Java 프로그램에로드하고 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() 메소드를 사용하여 Jar에서 Class를로드 할 수 있습니다. 그리고 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'로 캐스팅 될 수 없습니다. 항상 두 개의 다른 클래스 로더를 통해 클래스를 두 번로드했음을 의미합니다. 이미 하드 코딩 된 참조로 인해 클래스가 정적으로로드되어 있고 구현을로드 할 때 두 번째 복사본을로드했습니다. 이 질문에 대한 답변은 게시되지 않았습니다. 오류가 발생한 이유를 설명 할 수는 있지만 해결 방법을 알려주는 정보가 충분하지 않으므로 (그리고 클래스 로더 전문 지식이 다소 오래되었습니다). –

+0

예. 문제는 클래스 로더 twise를로드하여 이제 수정했습니다. 고맙습니다. – Tharanga

답변

1

다른 클래스 로더가로드 한 동일한 클래스 정의는 JVM에서 두 개의 별개 클래스로 간주됩니다.

코드 "인 URLClassLoader.newInstance"다른 클래스 로더

첫 번째 (핸들러 # 매개 변수)다면입니다 : # 1 &이

두 번째 (inputObject) 인 com.hello.Request URLClassLoader의 : 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

관련 문제