diff --git "a/Ch09/item66/\353\204\244\354\235\264\355\213\260\353\270\214_\353\251\224\354\204\234\353\223\234\353\212\224_\354\213\240\354\244\221\355\236\210_\354\202\254\354\232\251\355\225\230\353\235\274.md" "b/Ch09/item66/\353\204\244\354\235\264\355\213\260\353\270\214_\353\251\224\354\204\234\353\223\234\353\212\224_\354\213\240\354\244\221\355\236\210_\354\202\254\354\232\251\355\225\230\353\235\274.md" new file mode 100644 index 0000000..dfa2c1d --- /dev/null +++ "b/Ch09/item66/\353\204\244\354\235\264\355\213\260\353\270\214_\353\251\224\354\204\234\353\223\234\353\212\224_\354\213\240\354\244\221\355\236\210_\354\202\254\354\232\251\355\225\230\353\235\274.md" @@ -0,0 +1,75 @@ +# item66. 네이티브 메서드는 신중히 사용하라 +> 네이티브 메서드가 성능을 개선해주는 일은 많지 않다. 저수준 자원이나 네이티브 라이브러리를 사용해야만 해서 어쩔 수 없더라도 네이티브 코드는 최소한만 사용하고 철저히 테스트하라. 네이티브 코드 안에 숨은 단 하나의 버그가 어플리케이션 전체를 훼손할 수 있으므로 주의하라 + +- 자바 네이티브 인터페이스(Java Native Interface, JNI): 자바 언어와 네이티브(C/C++) 언어 간의 상호 작용을 위한 인터페이스 + - 자바에서 JNI 함수를 사용하여 클래스를 작성 + - C/C++ 코드에서 JNI 함수를 사용하여 자바 클래스 및 메소드 호출 + - C/C++ 코드를 컴파일하여 JNI 라이브러리를 생성하고, 자바에서 이 라이브러리를 로드하여 사용 +``` +// 자바 코드 +public class MyClass { + public static void myMethod(String str) { + System.out.println(str); + } +} + +// C/C++ 코드 +#include + +JNIEXPORT void JNICALL Java_MyClass_myMethod(JNIEnv *env, jclass clazz, jstring str) { + const char *cstr = env->GetStringUTFChars(str, nullptr); + printf("%s\n", cstr); + env->ReleaseStringUTFChars(str, cstr); +} +``` + +## 전통적인 네이티브 메서드의 주요 쓰임 +### 1. 레지스트리 같은 플랫폼 특화 기능 +- 하지만 자바가 성숙해가면서 (OS 같은) 하부 플랫폼의 기능들을 점차 흡수하고 있다 +- 네이티브 메서드를 사용할 필요가 계속 줄어들고 있다 +- 자바 9은 새로운 process API를 추가해 OS 프로세스에 접근하는 길을 열어주었다 +```java +public class JavaProcess { + public static void printProcessInfo(){ + ProcessHandle processHandle = ProcessHandle.current(); + ProcessHandle.Info processInfo = processHandle.info(); + + System.out.println("processHandle.pid(): " + processHandle.pid()); + System.out.println("processInfo.arguments(): " + processInfo.arguments()); + System.out.println("processInfo.command(): " + processInfo.command()); + System.out.println("processInfo.startInstant(): " + processInfo.startInstant()); + System.out.println("processInfo.user(): " + processInfo.user()); + } + public static void main(String[] args) { + printProcessInfo(); + } +``` +``` +> Task :streetdrop-api:JavaProcess.main() +processHandle.pid(): 40162 +processInfo.arguments(): Optional[[Ljava.lang.String;@232204a1] +processInfo.command(): Optional[/Users/siyeonson/Library/Java/JavaVirtualMachines/openjdk-19.0.2/Contents/Home/bin/java] +processInfo.startInstant(): Optional[2023-09-02T21:04:11.209Z] +processInfo.user(): Optional[siyeonson] +``` + +### 2. 네이티브 코드로 작성된 기존 라이브러리를 사용한다 +- 대체할 만한 자바 라이브러리가 없는 네이티브 라이브러리를 사용해야 할 때는 네이티브 메서드를 써야 한다 + + +### 3. 성능 개선을 목적으로 성능에 결정적인 영향을 주는 영역만 따로 네이티브 언어로 작성한다 +- 성능을 개선할 목적으로 네이티브 메서드를 사용하는 것은 거의 권장하지 않는다 +- JVM이 엄청난 속도로 발전하여, 대부분 작업에서 지금의 자바는 다른 플랫폼에 견줄만한 성능을 보인다 + +## 네이티브 메서드의 단점 +### 1. 메모리 훼손 오류 +- 네이티브 언어가 안전하지 않으므로 네이티브 메서드를 사용하는 어플리케이션도 메모리 훼손 오류로부터 더 이상 안전하지 않다 +- 가비지 컬렉터가 네이티브 메모리는 자동 회수하지 못하고, 심지어 추적조차 할 수 없다 + +### 2. 이식성 +- 네이티브 언어는 자바보다 플랫폼을 많이 타서 이식성도 낮고 디버깅도 더 어렵다 + +### 3. 성능과 비용, 가독성 +- 주의하지 않으면 속도가 오히려 느려질 수 있다 +- 자바 코드와 네티이브 코드의 경계를 넘나들 때마다 비용도 추가된다 +- 네이티브 메서드와 자바 코드 사이의 '접착 코드(glue code)'를 작성해야 하는데, 이는 귀찮은 작업이거니와 가독성도 떨어진다 \ No newline at end of file