화요일, 7월 02, 2013

[B급 프로그래머] JNI 함정과 우수 사례

지난번에 올려드린 [독서광] The Java Native Interface: Programmer's Guide and Specification이 대박은 아니지만 중박을 치면서 부족한 부분을 다시 한번 정리해드려야 겠다는 생각이 들었다. 그래서 오늘은 Best practices for using the Java Native Interface: Techniques and tools for averting the 10 most common JNI programming mistakes에서 개발자들이 JNI 프로그래밍 도중 흔히 저지르는 10가지 실수를 정리해봤다.

  1. Not caching method IDs, field IDs, and classes(캐시하지 않음): 메소드 ID, 필드 ID, 클래스를 캐시하지 않고 자주 native 쪽에서 참조할 경우 JVM이 클래스 계층을 오르락내리락하느라 무척 바빠진다. 그 결과 성능 저하가 생긴다.
  2. Triggering array copies(배열 복사 유도): JNI에서 배열은 값비싼 자원이다. 따라서 전체 배열에 접근하지 않고 반드시 필요한 부분만 접근하는 절약 정신이 요구된다. 예를 들어, long 담긴 배열에 접근할 경우 전체를 복사하는 GetLongArrayElements 대신 일부만 복사하는 GetLongArrayRegion을 사용할 수는 없는지 유심히 살펴볼 필요가 있다.
  3. Reaching back instead of passing parameters(매개변수 전달 대신 역참조): 사람들은 정보 은닉 관점에서 구조체나 클래스 객체에 여러 자료를 담아 전달하는 방식을 선호한다. 하지만 JNI에서 객체를 전달한 다음 객체에서 값을 얻기 위해 JNI 호출을 여러 번 하게 되면 굼벵이로 변한다. 따라서 처음부터 자료를 풀어헤쳐 개별 매개변수 형태로 전달하는 편이 훨씬 유리하다.
  4. Choosing the wrong boundary between native and Java code(잘못된 경계): 자바와 natvie 쪽 코드를 잘 분리해 자바에서 native로 native에서 자바로 호출이 최소로 일어나도록 만들어야 한다. 설계와도 관련이 있기 때문에 의외로 이 부분에 대해 실수하기 쉽다.
  5. Using many local references without informing the JVM(너무 많은 지역 참조): 지역 참조를 많이 할 경우 JVM 입장에서 무척 부담스럽다. 따라서 지역 참조를 될 수 있으면 적게 하고, 불필요한 지역 참조는 명시적으로 제거하는 편이 JVM 메모리 관리에 유리하다. 16개 이상 지역 참조가 필요할 경우 명시적으로 JVM에 이를 알려서 최적화가 가능하게 하자.
  6. Using the wrong JNIEnv(JNIEnv 오류): JNIEnv는 스레드 단위로 존재해야 한다. 스레드끼리 공유하거나 넘기면 절대 안 된다.
  7. Not checking for exceptions(예외 점검 미비): 예외를 일으킬 수 있는 JNI 함수 호출 다음에는 반드시 예외를 점검해야 한다. 이를 망각하면 나중에 (거꾸로) 대박 날지도...
  8. Not checking return values(반환값 점검 미비): JNI 함수 중에 결과를 반환하는 경우에 예외와 마찬가지로 제대로 검사해서 문제가 생겼을 경우 적절히 처리해야 한다.
  9. Using array methods incorrectly(배열 메소드 오용): 배열 메소드 쌍이 맞지 않으면 메모리 누수나 메모리 부족 현상이 생긴다.
  10. Using global references incorrectly(전역 참조 오용): 지역 참조만큼이나 전역 참조도 적절한 시점에서 잊어버리지 말고 해제해야 한다. JVM에서 메모리 누수 문제는 예상 외로 심각한 사태를 불러일으킬지도 모른다.

지난번과 중복되는 내용도 있고 새로 나온 내용도 있을 것이다. 얼마나 이런 실수가 많았으면, 아티클에서 문제 회피를 위한 표까지 정리해주었겠는가? T_T 다음 표를 참조해서 JNI 프로그래밍을 할 때마다 각성하면 좋겠다.

캐시하지 않음배열 복사 유도잘못된 경계너무 많은 역참조너무 많은 지역 참조JNIEnv 오류예외 점검 미비반환값 점검 미비배열 메소드 오용전역 참조 오용
JNI 명세 확인XXX
메소드 추적XXXXXXX
verbose:jniX
코드 검토XXXXXXXXXX
EOB

댓글 없음:

댓글 쓰기