MutableCallSite — 타깃이 보통 필드처럼 동작하는 콜 사이트
MutableCallSite — 타깃이 보통 필드처럼 동작하는 콜 사이트
MutableCallSite는 타깃 변수가 보통 필드(ordinary field) 처럼 동작하는 CallSite예요. MutableCallSite에 연결된 invokedynamic 명령어는 사이트의 현재 타깃에 모든 호출을 위임해요. mutable 콜 사이트의 dynamic invoker도 마찬가지로 사이트의 현재 타깃에 각 호출을 위임해요.
본문
타깃을 여러 번 바꿔야 하는 상황, 즉 메서드 핸들 체인에 상태 변수(state variable) 를 도입하고 싶을 때 유용해요. 다음은 메서드 핸들 체인에 상태 변수를 도입하는 mutable 콜 사이트 예시예요.
MutableCallSite name = new MutableCallSite(MethodType.methodType(String.class));
MethodHandle MH_name = name.dynamicInvoker();
MethodType MT_str1 = MethodType.methodType(String.class);
MethodHandle MH_upcase = MethodHandles.lookup()
.findVirtual(String.class, "toUpperCase", MT_str1);
MethodHandle worker1 = MethodHandles.filterReturnValue(MH_name, MH_upcase);
name.setTarget(MethodHandles.constant(String.class, "Rocky"));
assertEquals("ROCKY", (String) worker1.invokeExact());
name.setTarget(MethodHandles.constant(String.class, "Fred"));
assertEquals("FRED", (String) worker1.invokeExact());
// (변이는 무한히 계속될 수 있다)
같은 콜 사이트는 한 번에 여러 곳에서 쓰일 수 있어요. 예를 들어 두 개의 워커가 같은 콜 사이트를 공유하면, 타깃을 바꿀 때 두 워커 모두 새 값을 보게 돼요.
타깃 값의 비동기화(non-synchronization)
mutable 콜 사이트의 타깃에 쓰는 것은 다른 스레드가 갱신된 값을 알게 하지 않아요. 갱신된 콜 사이트에 대해 적절한 동기화 동작을 수행하지 않는 스레드는 옛 타깃 값을 캐시하고 새 타깃 값을 오래도록(무한히) 늦게 쓸 수 있어요. 이는 자바 메모리 모델을 객체 필드에 적용했을 때의 정상적인 결과예요.
MutableCallSite.syncAll(MutableCallSite[] sites) 연산은 다른 동기화 방법이 없어도 스레드가 새 타깃 값을 받아들이도록 강제하는 방법을 제공해요.
상속 구조는 다음과 같아요.
java.lang.Object
java.lang.invoke.CallSite
java.lang.invoke.MutableCallSite
대표적인 하위 클래스로 AbstractRelinkableCallSite가 있어요.
키 메서드
getTarget()— 콜 사이트의 현재 타깃 메서드를 반환해요.setTarget(MethodHandle newTarget)— 콜 사이트의 타깃 메서드를 일반적인 필드 할당처럼 갱신해요.dynamicInvoker()— 이 콜 사이트에 연결된invokedynamic명령어와 동등한 메서드 핸들을 만들어요.
static 메서드
static void syncAll(MutableCallSite[] sites)— 주어진 콜 사이트들이 각자의 타깃 값을 최신 상태로 보도록 동기화해요.