forked from depromeet/effective-java-study
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Item66]: 네이티브 메서드는 신중히 사용하라 (depromeet#147)(시연)
- Loading branch information
Showing
1 changed file
with
75 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 <jni.h> | ||
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)'를 작성해야 하는데, 이는 귀찮은 작업이거니와 가독성도 떨어진다 |