다운콜 핸들
네이티브 함수를 호출합니다
다운콜 핸들은(는) CoddyKit의 무료 Java Academy 강의입니다. 이것은 4개 중 3번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Java Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Java Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
네이티브 함수 호출
하향 호출은 Java에서 네이티브 코드로 내려가는 호출입니다. FFM은 각 네이티브 함수를 Linker로 만든 MethodHandle로 나타냅니다.
이 레슨에서는 C 함수를 찾고, 서술하고, 호출하는 과정을 살펴봅니다.
네이티브 링커
Linker.nativeLinker()는 현재 실행 중인 플랫폼에 맞는 링커를 반환합니다. 링커는 C 호출 규약을 알고 있으며 네이티브 함수용 핸들을 만들 수 있습니다.
import java.lang.foreign.Linker;
public class Main {
public static void main(String[] args) {
Linker linker = Linker.nativeLinker();
System.out.println("Got native linker: " + linker);
}
}심볼 찾기
함수의 주소가 필요합니다. linker.defaultLookup()은 표준 C 라이브러리를 검색하고, SymbolLookup.libraryLookup(name, arena)은 특정 공유 라이브러리를 불러옵니다.
import java.lang.foreign.*;
public class Main {
public static void main(String[] args) {
Linker linker = Linker.nativeLinker();
SymbolLookup stdlib = linker.defaultLookup();
MemorySegment addr = stdlib.find("strlen").orElseThrow();
System.out.println("strlen address found: " + addr);
}
}서명 설명하기
FunctionDescriptor는 레이아웃을 사용해 C 함수 서명을 설명합니다. size_t strlen(const char*)에서는 반환값이 긴 정수형이고 인수는 포인터(ADDRESS)입니다.
import java.lang.foreign.*;
public class Main {
public static void main(String[] args) {
FunctionDescriptor desc = FunctionDescriptor.of(
ValueLayout.JAVA_LONG, // return: size_t
ValueLayout.ADDRESS); // arg: const char*
System.out.println("Descriptor: " + desc);
}
}핸들 만들기
심볼과 서술자를 downcallHandle로 결합하면 Java 메서드처럼 호출할 수 있는 MethodHandle을 얻습니다.
import java.lang.foreign.*;
import java.lang.invoke.MethodHandle;
public class Main {
public static void main(String[] args) {
Linker linker = Linker.nativeLinker();
MethodHandle strlen = linker.downcallHandle(
linker.defaultLookup().find("strlen").orElseThrow(),
FunctionDescriptor.of(ValueLayout.JAVA_LONG, ValueLayout.ADDRESS));
System.out.println("Handle ready: " + strlen.type());
}
}함수 호출하기
strlen을 호출하려면 네이티브 문자열을 가리키는 포인터를 전달해야 합니다. 문자열을 아레나에 할당한 다음 핸들을 invoke합니다. 결과는 Java의 긴 정수 값으로 반환됩니다.
import java.lang.foreign.*;
import java.lang.invoke.MethodHandle;
public class Main {
public static void main(String[] args) throws Throwable {
Linker linker = Linker.nativeLinker();
MethodHandle strlen = linker.downcallHandle(
linker.defaultLookup().find("strlen").orElseThrow(),
FunctionDescriptor.of(ValueLayout.JAVA_LONG, ValueLayout.ADDRESS));
try (Arena arena = Arena.ofConfined()) {
MemorySegment str = arena.allocateUtf8String("Hello, FFM");
long len = (long) strlen.invoke(str);
System.out.println("Length = " + len);
}
}
}타입 매핑
각 C 타입은 다음과 같이 레이아웃에 매핑됩니다.
int는ValueLayout.JAVA_INT로long/size_t는JAVA_LONG으로double은JAVA_DOUBLE로- 모든 포인터는
ADDRESS로
이 매핑을 올바르게 지정하는 것이 중요합니다. 잘못 지정하면 호출로 인해 데이터가 손상됩니다.
포인터를 반환하는 함수
C 함수가 포인터를 반환하면 핸들은 길이가 0인 MemorySegment를 반환합니다. 시작 위치 너머의 데이터를 읽으려면 재해석하여 reinterpret(byteSize)로 올바른 크기를 지정해야 합니다.
인수가 많은 함수 전달하기
FunctionDescriptor.of(returnLayout, arg1, arg2, ...)에는 인수가 순서대로 나열됩니다. 반환값이 없는 함수에는 반환 레이아웃 없이 FunctionDescriptor.ofVoid(args...)를 사용합니다.
import java.lang.foreign.*;
public class Main {
public static void main(String[] args) {
// int (*)(const char*, int)
FunctionDescriptor two = FunctionDescriptor.of(
ValueLayout.JAVA_INT, ValueLayout.ADDRESS, ValueLayout.JAVA_INT);
// void (*)(int)
FunctionDescriptor noReturn = FunctionDescriptor.ofVoid(ValueLayout.JAVA_INT);
System.out.println(two + " / " + noReturn);
}
}throws로 오류 처리하기
MethodHandle.invoke는 throws Throwable을 선언하므로 호출 메서드는 이를 처리하거나 선언해야 합니다. 따라서 예제에서 throws Throwable을 선언합니다.
핸들 캐싱하기
하향 호출 핸들을 만드는 작업은 비교적 비용이 많이 들므로 한 번만 만든 뒤 재사용하세요. 일반적인 패턴은 클래스 초기화 중에 핸들을 static final 필드에 바인딩하고 여러 번 호출하는 것입니다.
핸들 자체는 여러 스레드에서 동시에 호출해도 안전합니다.
빠른 확인
C 포인터 인수를 어떻게 설명하는지 떠올려 보세요.
복습
네이티브 함수를 호출하는 방법을 배웠습니다.
- 심볼을 찾으려면
Linker.nativeLinker()와SymbolLookup을 함께 사용 FunctionDescriptor는 레이아웃으로 서명을 설명downcallHandle은 호출할 수 있는MethodHandle을 제공하며, 이를invoke함- 포인터는
ADDRESS에 매핑되고invoke는Throwable을 발생시킴
다음으로는 레이아웃과 구조체를 사용해 복잡한 네이티브 데이터를 설명합니다.
자주 묻는 질문
“다운콜 핸들” 강의는 무료인가요?
네 — “다운콜 핸들” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Java Academy 강의 전체를 잠금 해제할 수 있습니다. Java Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
“다운콜 핸들”에서 뭘 배우나요?
네이티브 함수를 호출합니다 브라우저에서 직접 실행하는 실습 코드로 Java Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
Java Academy을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 Java Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 3번째 강의입니다.
“다운콜 핸들” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 Java Academy 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 Java Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.