`jdk.dynalink.support.AbstractRelinkableCallSite`은 Java 언어의 동적 링크 프레임워크인 `Dynalink`에서 사용되는 추상 클래스입니다. 이 클래스는 `CallSite` 인터페이스를 구현하며, 동적 메서드 호출에 대한 재링크(relink) 작업을 지원합니다.
`Dynalink`는 다이나믹 언어에 특화된 동적 링크 프레임워크로, 메서드나 프로퍼티 등의 동적인 접근을 지원합니다. 이 프레임워크는 호출 대상 객체의 타입과 메서드 시그니처 등을 분석하여 호출 대상 객체의 메서드나 프로퍼티를 호출하는 코드를 생성합니다. 이때, 호출 대상 객체의 타입이나 메서드 시그니처가 변경될 경우, 이에 대한 재링크 작업이 필요합니다.
`AbstractRelinkableCallSite`는 이러한 재링크 작업을 위한 추상 클래스로, `linkToTarget` 메서드를 제공합니다. 이 메서드는 호출 대상 객체의 타입이나 메서드 시그니처가 변경될 때 호출됩니다. 이 메서드는 `CallSite`의 `getTarget` 메서드로부터 현재 호출 대상 객체를 가져온 후, 이를 새로운 타입이나 시그니처에 맞게 변환하여 다시 `CallSite`의 `setTarget` 메서드를 통해 설정합니다. 이렇게 함으로써, 이후의 동적 메서드 호출은 새로운 타입이나 시그니처에 맞게 호출되게 됩니다.
`AbstractRelinkableCallSite`는 `RelinkableCallSite` 인터페이스를 상속하므로, 이 클래스를 상속하여 재링크 작업에 필요한 추가적인 메서드를 구현할 수 있습니다. 또한, `AbstractRelinkableCallSite`는 `ConstantCallSite` 클래스와 함께 사용될 수도 있습니다. 이때, `ConstantCallSite`는 최초의 메서드 호출에서 호출 대상 객체를 설정하고, `AbstractRelinkableCallSite`는 이후의 재링크 작업을 처리합니다.
이와 같이 `AbstractRelinkableCallSite` 클래스는 `Dynalink`에서 동적 메서드 호출에 대한 재링크 작업을 처리하기 위한 중요한 클래스 중 하나입니다.`AbstractRelinkableCallSite` 클래스는 `CallSite` 인터페이스의 메서드 외에도 몇 가지 중요한 메서드를 제공합니다. 가장 중요한 메서드는 `linkToTarget` 메서드이며, 이 메서드는 호출 대상 객체의 타입이나 메서드 시그니처가 변경될 때 호출됩니다. 이 메서드는 `CallSite` 인터페이스의 `getTarget` 메서드를 호출하여 현재 호출 대상 객체를 가져온 후, 새로운 타입이나 시그니처에 맞게 변환한 후 `CallSite` 인터페이스의 `setTarget` 메서드를 호출하여 새로운 호출 대상 객체를 설정합니다.
`AbstractRelinkableCallSite` 클래스는 또한 `RelinkableCallSite` 인터페이스를 구현합니다. `RelinkableCallSite` 인터페이스는 재링크 작업을 수행하는 메서드를 정의하며, `AbstractRelinkableCallSite` 클래스는 이 인터페이스에서 정의된 `relink` 메서드를 구현합니다. `relink` 메서드는 `linkToTarget` 메서드와 비슷하지만, 재링크 작업에 필요한 추가적인 작업을 수행합니다. 예를 들어, `relink` 메서드는 현재 호출 대상 객체가 새로운 타입에 대한 캐시를 가지고 있는지 검사하고, 있을 경우 이를 재사용합니다. 이러한 추가 작업은 재링크 작업을 더욱 효율적으로 수행할 수 있도록 합니다.
`AbstractRelinkableCallSite` 클래스는 추상 클래스이기 때문에 직접 인스턴스화할 수 없습니다. 대신에 이 클래스를 상속하여 새로운 클래스를 정의하고, `linkToTarget` 메서드와 `relink` 메서드를 오버라이드하여 필요한 작업을 수행할 수 있습니다. 이러한 방식으로 `Dynalink`는 자바 언어에서 동적 메서드 호출을 효율적으로 처리할 수 있게 됩니다.`AbstractRelinkableCallSite` 클래스의 예제 코드를 작성해보겠습니다.
import jdk.dynalink.DynamicLinker;
import jdk.dynalink.DynamicLinkerFactory;
import jdk.dynalink.linker.CallSite;
import jdk.dynalink.linker.LinkRequest;
import jdk.dynalink.linker.MethodHandleTransformer;
import jdk.dynalink.support.AbstractRelinkableCallSite;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
public class RelinkableCallSiteExample {
public static void main(String[] args) throws Throwable {
DynamicLinker linker = new DynamicLinkerFactory().createLinker();
CallSite callSite = linker.bootstrap(
MethodHandles.lookup(),
"sayHello",
MethodType.methodType(void.class, Object.class)
);
MethodHandle target = MethodHandles.lookup().findStatic(
RelinkableCallSiteExample.class,
"hello",
MethodType.methodType(void.class, Object.class)
);
// link to initial target
callSite = new MyRelinkableCallSite(callSite.getTarget(), callSite.type());
// invoke call site with String argument
callSite.getTarget().invoke("World");
// relink call site to new target
callSite = ((AbstractRelinkableCallSite) callSite).relink(
new LinkRequest(
callSite.type(),
MethodType.methodType(void.class, String.class),
new MethodHandleTransformer() {
@Override
public MethodHandle transform(MethodHandle target) {
return target.asType(MethodType.methodType(void.class, String.class));
}
}
)
);
// invoke call site with int argument
callSite.getTarget().invoke(123);
}
public static void hello(Object name) {
System.out.println("Hello, " + name + "!");
}
private static class MyRelinkableCallSite extends AbstractRelinkableCallSite {
public MyRelinkableCallSite(MethodHandle target, MethodType type) {
super(target, type);
}
@Override
protected CallSite relink(MethodType type, MethodHandle target, MethodHandleTransformer transformer) {
// transform target method handle using the provided transformer
target = transformer.transform(target);
// create new call site with the transformed target
return new MyRelinkableCallSite(target, type);
}
}
}
이 예제 코드에서는 `DynamicLinker`를 사용하여 `CallSite`를 생성합니다. 이 `CallSite`는 `sayHello` 메서드를 호출하도록 설정되어 있습니다. 이 메서드는 `Object` 타입의 인수를 받아들이고 반환 값이 없습니다.
다음으로, `hello` 메서드를 정의합니다. 이 메서드는 `Object` 타입의 `name` 인수를 받아들이고, `Hello, [name]!`과 같은 형식의 메시지를 출력합니다.
`MyRelinkableCallSite` 클래스는 `AbstractRelinkableCallSite` 클래스를 상속합니다. `MyRelinkableCallSite` 클래스에서는 `relink` 메서드를 오버라이드하여 새로운 호출 대상을 생성할 때, `MethodHandleTransformer`를 사용하여 새로운 호출 대상에 대한 변환 작업을 수행합니다.