IT story

Java 클래스가 런타임에 자신에게 메소드를 추가 할 수 있습니까?

hot-time 2020. 12. 30. 19:17
반응형

Java 클래스가 런타임에 자신에게 메소드를 추가 할 수 있습니까?


static누군가가이 클래스에 대해 리플렉션을 수행하는 경우 컴파일 타임에 정의되지 않았더라도 새 메서드를 볼 수 있도록 클래스가 런타임에 자신에게 메서드를 추가 할 수 있습니까 (예 : 블록에서)?

배경:

내가 사용하는 프레임 워크는 규칙에 Action따라 doAction(...)메서드 가있는 클래스가 정의 될 것으로 예상 합니다. 프레임 워크는 런타임에 이러한 클래스를 검사하여 doAction()메서드 에서 사용할 수있는 매개 변수 유형을 확인합니다 . 예 : doAction ( String a, Integer b)

각 클래스 doAction()가 검사 할 때 적시에 다양한 매개 변수를 사용하여 메서드 를 프로그래밍 방식으로 생성 할 수 있기를 바랍니다 . 메서드의 본문은 비어있을 수 있습니다.


간단하지 않습니다. 클래스 로더에 의해 클래스가로드되면로드 된 클래스의 메서드를 변경할 방법이 없습니다. 클래스가 요청되면 클래스 로더가 클래스를로드하고 링크 합니다. 그리고 링크 된 코드를 변경하거나 메소드를 추가 / 제거하는 방법 (Java 사용)이 없습니다.

내 마음에 떠오르는 유일한 트릭은 클래스 로더를 가지고 노는 것입니다. 사용자 정의 클래스 로더를 삭제하면 해당 클래스 로더에 의해로드 된 클래스도 삭제되거나 액세스 할 수 없습니다. 내 마음에 떠오르는 생각은

  1. 하나의 사용자 정의 클래스 로더 구현
  2. 해당 사용자 정의 클래스 로더로 동적 클래스를 로드하십시오.
  3. 이 클래스의 업데이트 된 버전이있는 경우
  4. 사용자 정의 클래스 로더를 제거 하고
  5. 사용자 정의 클래스 로더의 새 인스턴스로이 클래스의 새 버전을로드합니다.

나는 이것이 해결책으로 이어 지거나 함정이 있는지 증명할 수없는 생각의 음식으로 남겨 둡니다 .

질문에 대한 간단한 대답 : 아니요, 리플렉션을 사용하여 필드의 내용을 변경할 수있는 것처럼로드 된 클래스를 변경할 수 없습니다. (필드를 추가하거나 제거 할 수도 없습니다).


Andres_D가 맞습니다. 사용자 정의 클래스 로딩을 사용하여 그렇게 할 수 있습니다. 여기에 자세한 방법이 있습니다. http://www.javaworld.com/javaworld/jw-06-2006/jw-0612-dynamic. html? page = 1

이 기사에서는 동적 Java 코드를 작성하는 방법을 설명합니다. 런타임 소스 코드 컴파일, 클래스 다시로드 및 프록시 디자인 패턴을 사용하여 동적 클래스를 호출자에게 투명하게 수정하는 방법에 대해 설명합니다.

실제로 오스트리아의 연구원은 다른 유형의 계층 구조로 클래스를 다시로드 할 수있는 JVM을 작성했습니다. 기존 스레드 저장 지점을 사용하여 개체와 모든 관련 참조 및 참조 된 콘텐츠의 완전한 '측면 유니버스'를 생성 한 다음 모든 필수 변경 사항으로 완전히 재편성되면 변경된 모든 클래스에서 간단히 교체하면됩니다. [1] 여기에 그들의 프로젝트 http://ssw.jku.at/dcevm/에 대한 링크가 있습니다 . 오라클의 후원은 확실히 향후 계획에 대한 흥미로운 추측을 만들어냅니다.

Java 1.4에 도입 된 JPDA의 Hot Swap 기능을 사용하여 표준 Java VM에서 메소드 본문 및 필드에 대한 덜 방해적인 변경이 이미 가능합니다.
docs.oracle.com/javase/1.4.2/docs/guide/jpda/enhancements. html # hotswap

이것이 첫 번째인지는 확실하지 않지만 2001 년에 Sun 직원이 작성한이 문서는 HotSpot to Hot Swap의 기능을 언급 한 초기 제안 중 하나 인 것으로 보입니다. [2]

참고

[1] T. Würthinger, C. Wimmer 및 L. Stadler, "Dynamic Code Evolution for Java", 2010 년 비엔나에서 프로그래밍의 원리 및 실습에 관한 제 8 회 국제 컨퍼런스에서 발표되었습니다.

[2] M. Dmitriev, "Towards flexible and safe technology for runtime evolution of java language applications,"in OOPSLA Workshop on Engineering Complex Object-Oriented Systems for Evolution, 2001.


나는 나 자신과 같은 것을 시도한 적이 없지만 ASM , cglibJavassist를 살펴보아야 합니다.


아니요, Java에서는 (쉽게) 불가능합니다.

마치 동적 프로그래밍 언어 인 것처럼 Java를 사용하려는 것 같습니다. 예를 들어 Ruby에는 개방형 클래스가 있습니다. 런타임에 Ruby 클래스에서 메소드를 추가하고 제거 할 수 있습니다. Ruby에서는 클래스에없는 메서드를 호출하려고 할 때 호출되는 "메서드 누락"메서드가 클래스에있을 수도 있습니다. 그런 것 또한 자바에 존재하지 않습니다.

JVM, JRuby에서 실행되는 Ruby 버전이 있으며 JVM에서 개방형 클래스가 작동하도록하려면 매우 어려운 트릭을 수행해야합니다.


doAction생성 된 메소드가 원하는대로 수행 하는 메소드를 가질 수 있습니다 . 생성해야하는 이유가 있습니까? 아니면 동적 일 수 있습니까?


asm, cglib 또는 javassist와 같은 도구 / 프레임 워크를 변경하는 바이트 코드가 필요하다고 생각합니다. Spring처럼 aspect / weaving을 통해이를 달성 할 수 있지만, 여전히 먼저 메서드를 정의해야한다고 생각합니다.


프록시가 도움이 될 수 있습니다. 그러나 메서드를 추가하거나 제거 할 때마다 프록시를 인스턴스화해야합니다.


메서드를 동적으로 추가 할 방법이없는 것 같습니다. 그러나 메소드 목록이나 다음과 같은 해시로 클래스를 준비 할 수 있습니다.

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashMap;

public class GenericClass {
    private HashMap<String, Method> methodMap = new HashMap<String, Method>();

    public Object call(String methodName,Object ...args) 
               throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        Method method = methodMap.get(methodName);
        return method.invoke(null, args);
    }

    public void add(String name,Method method){
        if(Modifier.isStatic(method.getModifiers()))
            methodMap.put(name, method);
    }

    public static void main(String[] args) {
        try   {
            GenericClass task = new GenericClass();
            task.add("Name",Object.class.getMethod("Name", new Class<?>[0]));
        } catch (NoSuchMethodException | SecurityException e) {
            e.printStackTrace();
        }
   }
}

반사를 사용하여 속성을 설정하거나 해제 할 수 있습니다.


내가 제안하는 것은 당신의 상황에 맞아야한다 : 1. 당신은 n 개의 메소드를 가진 MyClass 클래스를 가지고있다. 2. 다른 .java 소스 파일에서 컴파일하는 동안 클래스에없는 (n + 1) 번째 메소드를 포함하고 싶다.

My way to solve it is Inheritance. Create a new .java source file for a Class MyClassPlusOne extending the first class MyClass. Compile this class and use the object. How can I compile and deploy a java class at runtime?

class MyClassPlusOne extends MyClass
{
     void doAction(String a, Integer b)
     {
         int myNPlus1 = a+b;
         //add whatever you want before compiling this code
      }
}

I'm not sure that is possible. However, you could use AspectJ, ASM, etc. and weave these methods into the appropriate classes.

The other alternative is to use composition to wrap the target class and provide the doAction method. You would end up delegating to the target class in this case.

ReferenceURL : https://stackoverflow.com/questions/6680674/can-a-java-class-add-a-method-to-itself-at-runtime

반응형