[ITEM66] 네이티브 메서드는 신중히 사용하라

뚝딱이·2024년 2월 2일
0

이펙티브 자바

목록 보기
41/55
post-thumbnail

네이티브 메서드

네이티브 메서드란 C나 C++같은 네이티브 프로그래밍 언어로 작성한 메서드를 말한다. 즉, Java 소스코드에서 C/C++로 작성한 코드를 호출할 때 사용한다.

출처 : Guide to JNI

사용

public class HelloWorldJNI {
    static {
        System.loadLibrary("native");
    }
    public static void main(String[] args) {
        new HelloWorldJNI().sayHello();
    }
  //native method with no body
  public native void sayHello();
}

위와 같이 메서드를 선언하고 javac -h . HelloWorldJNI.java로 실행하면 아래와 같은 파일이 자동생성된다.

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
#ifndef _Included_HelloWorldJNI
#define _Included_HelloWorldJNI
#ifdef __cplusplus
extern "C" {
#endif
JNIEXPORT void JNICALL Java_HelloWorldJNI_sayHello
  (JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif

그리고 C++파일을 작성한다.

#include<iostream>
#include<jni.h>
#include "HelloWorldJNI.h"
void sayHello(){
  std::cout << "Hello from C++ !!" << std::endl;
}
JNIEXPORT void JNICALL Java_HelloWorldJNI_sayHello
  (JNIEnv* env, jobject thisObject) {
    sayHello();
}

그다음,
g++ -c -I”%JAVA_HOME%\include” -I”%JAVA_HOME%\include\win32" HelloWorldJNI.cpp로 실행하고 g++ -shared -o native.dll HelloWorldJNI.o를 통해 object file로 부터 dll file을 생성한다.

마지막으로 java HelloWorldJNI을 통해 java파일을 실행한다. 자세한 내용은 Guide to JNI를 참고하면 된다.

쓰임

레지스트리 같은 플랫폼 특화 기능을 사용한다.

자바가 성숙해가며 (OS 같은)하부 플랫폼의 기능들을 점차 흡수 => 네이티브 메서드 사용의 필요성 하락

예로 Java 9에서 새로 process API를 추가 -> OS 프로세스에 접근가능

private static void infoOfCurrentProcess() {
    ProcessHandle processHandle = ProcessHandle.current();
    ProcessHandle.Info processInfo = processHandle.info();

    log.info("PID: " + processHandle.pid());
    log.info("Arguments: " + processInfo.arguments());
    log.info("Command: " + processInfo.command());
    log.info("Instant: " + processInfo.startInstant());
    log.info("Total CPU duration: " + processInfo.totalCpuDuration());
    log.info("User: " + processInfo.user());
}
16:31:24.784 [main] INFO  c.b.j.process.ProcessAPIEnhancements - PID: 22640
16:31:24.790 [main] INFO  c.b.j.process.ProcessAPIEnhancements - Arguments: Optional[[Ljava.lang.String;@2a17b7b6]
16:31:24.791 [main] INFO  c.b.j.process.ProcessAPIEnhancements - Command: Optional[/Library/Java/JavaVirtualMachines/jdk-13.0.1.jdk/Contents/Home/bin/java]
16:31:24.795 [main] INFO  c.b.j.process.ProcessAPIEnhancements - Instant: Optional[2021-08-31T14:31:23.870Z]
16:31:24.795 [main] INFO  c.b.j.process.ProcessAPIEnhancements - Total CPU duration: Optional[PT0.818115S]
16:31:24.796 [main] INFO  c.b.j.process.ProcessAPIEnhancements - User: Optional[username]

네이티브 코드로 작성된 기존 라이브러리를 사용한다.

ex) 레거시 데이터를 사용하는 레거시 라이브러리

성능 개선을 목적으로 성능에 결정적인 형향을 주는 영역만 따로 네이티브 언어로 작성한다.

하지만, 성능을 개선할 목적으로 네이티브 메서드를 사용하는 것은 거의 권장하지 않는다. JVM은 엄청난 속도로 발전해와 지금의 자바는 다른 플랫폼에 견줄만한 성능을 보인다.

ex) 자바1.1 시절 BigInteger는 C로 작성한 고성능 라이브러리에 의지했으나, 3때 순수 자바로 다시 구현되어 튜닝해 더 네이티브 구현보다도 더 빨라졌다.

하지만 네이티브 라이브러리 쪽은 GNU 다중 정밀 연산 라이브러리를 필두로 개선 작업이 계속 되었으므로 정말로 고성능의 다중 정밀 연산이 필요하다면, 고려해도 좋다.

단점

안전하지 않으므로 메모리 훼손 오류로부터 더 이상 안전하지 않다.

이식성이 낮다.

디버깅도 어렵다.

주의하지 않으면 속도가 오히려 느려질 수 있다.

가비지 컬렉터가 네이티브 메모리는 자동회수하지 못하고 추적조차 할 수 없다.

자바 코드와 네이티브 코드의 경계를 넘나들 때마다 비용도 추가된다.

접착코드 작성은 귀찮고 가독성이 떨어진다.

출처

이펙티브 자바 3/E
Guide to JNI
Java 9 Process API Improvements

profile
백엔드 개발자 지망생

0개의 댓글

관련 채용 정보