DynamicLinker

DynamicLinker (콜 사이트 연결 관리자)

RelinkableCallSite 객체를 위한 링커입니다. Dynalink를 쓸 때 핵심이 되는 객체로, 콜 사이트를 사용 가능한 언어 런타임들의 링커(GuardingDynamicLinker 객체)와 조율해 연결합니다.

출처: Java API Reference

본문

Dynalink를 사용하려면 DynamicLinkerFactory로 동적 링커를 하나 이상 만들고, invokedynamic 부트스트랩 메서드에서 그 link(RelinkableCallSite) 메서드를 호출해 콜 사이트를 관리하면 됩니다. 전형적인 사용 패턴은 이래요.

class MyLanguageRuntime {
    private static final GuardingDynamicLinker myLanguageLinker = new MyLanguageLinker();
    private static final DynamicLinker dynamicLinker = createDynamicLinker();
    private static DynamicLinker createDynamicLinker() {
        final DynamicLinkerFactory factory = new DynamicLinkerFactory();
        factory.setPrioritizedLinker(myLanguageLinker);
        return factory.createLinker();
    }
    public static CallSite bootstrap(MethodHandles.Lookup lookup, String name, MethodType type) {
        return dynamicLinker.link(
            new SimpleRelinkableCallSite(
                new CallSiteDescriptor(lookup, parseOperation(name), type)));
    }
    private static Operation parseOperation(String name) { /* ... */ }
}

위 예처럼 정적 링커 인스턴스 하나만 쓰는 경우가 많지만, 언어 런타임이 '컨텍스트 클래스 로더' 개념을 가진다면 클래스 로더마다 동적 링커를 하나씩 만들어 그 로더에 보이는 다른 언어 런타임의 링커를 포함시키는 게 좋아요(DynamicLinkerFactory.setClassLoader(ClassLoader) 참고).

제공해야 할 것은 세 가지입니다. 첫째, 자신의 언어를 위한 GuardingDynamicLinker입니다. 자체 객체 모델이나 타입 변환이 없으면 구현할 필요가 없고 setPrioritizedLinker만 호출하지 않으면 돼요. 둘째, 콜 사이트를 나타내는 클래스 선택인데 프로그램 성능에 영향을 줄 수 있습니다. SimpleRelinkableCallSite 대신 ChainedCallSite를 쓸 수도 있고, 실험해서 런타임에 맞는 것을 고르면 됩니다. 셋째, 콜 사이트에 CallSiteDescriptor를 제공해야 합니다. 이것은 룩업을 수행하는 클래스, 호출되는 연산, 메서드 시그니처 등 콜 사이트에 대한 모든 정보를 담은 불변 객체입니다. 콜 사이트 이름이나 정적 매개변수에서 연산을 인코딩·디코딩하는 방식은 사용자가 정해야 하며, 위 예의 parseOperation이 그 역할을 합니다.

주요 메서드

  • link(T callSite)invokedynamic 콜 사이트를 연결합니다. 콜 사이트에 이 링커의 재연결 메커니즘을 호출하는 메서드 핸들을 설치해요. 다음에 콜 사이트가 호출되면 실제로 호출된 인자에 맞춰 연결됩니다. 연결된 콜 사이트 자신을 반환하므로 호출 체이닝이 쉽습니다.

  • getLinkerServices() — 개별 언어별 링커에 노출되는, 이 클래스의 링커 서비스를 나타내는 LinkerServices 객체를 반환합니다. 보통은 link만 신경 쓰지만 특정 메서드 핸들을 조회하거나 타입 변환기에 접근할 때 하위 서비스를 직접 쓸 수도 있어요.

  • getLinkedCallSiteLocation() — 현재 스레드에서 연결 중인 invokedynamic 콜 사이트의 위치를 기술하는 스택 트레이스 요소를 반환합니다.

더 알아보기

Java 공식 API