SymbolLookup — 외부 라이브러리에서 심볼의 주소를 찾는 인터페이스
SymbolLookup — 외부 라이브러리에서 심볼의 주소를 찾는 인터페이스
SymbolLookup은 하나 이상의 라이브러리에서 심볼(symbol)의 주소를 찾아내는 기능을 제공하는 인터페이스예요. 심볼은 함수나 전역 변수처럼 이름이 붙은 엔티티를 뜻해요.
본문
이 인터페이스는 java.lang.foreign 패키지의 일부로, preview API예요. 즉 preview 기능을 활성화해야 쓸 수 있고, 향후 릴리스에서 제거되거나 영구 기능으로 승격될 수 있어요.
심볼 룩업은 특정 라이브러리(또는 여러 라이브러리)를 기준으로 만들어진 뒤, find(String) 메서드가 심볼 이름을 받아 해당 라이브러리에서 그 심볼의 주소를 반환해요. 심볼의 주소는 길이가 0인 메모리 세그먼트(zero-length memory segment) 로 모델링되는데, 다양한 방식으로 사용돼요.
Linker에 전달해 downcall 메서드 핸들로 만들고, 그 세그먼트 주소의 외부 함수를 호출할 수 있어요.- 기존 downcall 메서드 핸들에, 밑에 있는 외부 함수의 인자로 전달할 수 있어요.
- 다른 메모리 세그먼트 안에 저장할 수 있어요.
- 전역 변수를 뒷받침하는 메모리 영역에 접근하는 데 쓸 수 있어요 (먼저 세그먼트를 리사이징해야 해요).
심볼 룩업 얻기
팩토리 메서드 SymbolLookup.libraryLookup(String, Arena)와 SymbolLookup.libraryLookup(Path, Arena)는 운영체제가 아는 라이브러리를 위한 심볼 룩업을 만들어요. 라이브러리는 이름이나 경로로 지정되고, 아직 로드되지 않았다면 로드돼요. 이 라이브러리 룩업의 수명은 Arena가 제어해요. 예를 들어 confined arena를 쓰면, 그 arena가 닫힐 때 연결된 라이브러리가 언로드돼요.
try (Arena arena = Arena.ofConfined()) {
SymbolLookup libGL = SymbolLookup.libraryLookup("libGL.so", arena); // 여기서 libGL.so 로드
MemorySegment glGetString = libGL.find("glGetString").orElseThrow();
...
} // 여기서 libGL.so 언로드
JNI를 통해 이전에 로드된 라이브러리(즉 System.load(String)·System.loadLibrary(String)로 로드된 라이브러리)는 특정 클래스 로더와 연결돼 있어요. 팩토리 메서드 loaderLookup()은 호출자의 클래스 로더와 연결된 모든 라이브러리를 위한 심볼 룩업을 만들어요.
이 인터페이스는 함수형 인터페이스라서 람다 표현식이나 메서드 참조의 할당 대상으로 쓸 수 있어요.