네이티브 코드를 호출하기 위해 유고 인민군 대신 JNI를 사용하시겠습니까?
JNA는 JNI에 비해 네이티브 코드를 부르기가 꽤 쉬워 보인다.어떤 경우에 JNI를 인민군보다 사용하겠습니까?
- JNA는 c++ 클래스의 매핑을 지원하지 않으므로 c++ 라이브러리를 사용하는 경우 jni 래퍼 필요
- 만약 당신이 많은 양의 메모리가 필요하다면.예를 들어 큰 바이트 버퍼를 반환하는 메서드를 호출하고 그 버퍼에서 무언가를 변경한 다음 이 바이트 버퍼를 사용하는 다른 메서드를 호출해야 합니다.이를 위해서는 이 버퍼를 c에서 java로 복사한 후 java에서 c로 다시 복사해야 합니다.이 경우 복사하지 않고 이 버퍼를 c로 유지 및 변경할 수 있기 때문에 jni는 퍼포먼스가 향상됩니다.
이것들은 내가 겪은 문제점들이다.아마 더 있을 거야그러나 일반적인 성능은 유고 인민군과 jni군 간에 크게 다르지 않으므로, 유고 인민군을 사용할 수 있는 곳이라면 어디든 사용하세요.
편집
이 답변은 꽤 인기가 있는 것 같습니다.다음은 몇 가지 추가 사항입니다.
- C++ 또는 COM을 매핑해야 할 경우 JNAserator의 크리에이터인 Oliver Chafic의 BridJ라는 라이브러리가 있습니다.그것은 아직 젊은 도서관이지만, 많은 흥미로운 특징들을 가지고 있다.
- Dynamic C / C++ / COM interop : C++ 메서드를 호출하여 C++ 오브젝트(및 Java로부터의 서브클래스 C++ 클래스!)를 만듭니다.
- 제네릭을 잘 사용한 간단한 유형 매핑(Pointers의 훨씬 뛰어난 모델 포함)
- 완전 유고 인민군 지원
- Windows, Linux, MacOS X, Solaris, Android에서 작동
- 메모리 복사는 JNA가 다이렉트 Byte Buffer를 지원하므로 메모리 복사는 피할 수 있다고 생각합니다.
따라서 가능하면 JNA나 BridJ를 사용하고, 퍼포먼스가 중요한 경우에는 jni로 되돌리는 것이 좋다고 생각합니다.네이티브 함수를 자주 호출할 필요가 있는 경우에는 퍼포먼스 저하가 눈에 띄기 때문입니다.
그런 일반적인 질문에 답하기는 어렵다.JNI에서는 타입 변환이 자바/네이티브 국경의 네이티브 측에 실장되어 있고, JNA에서는 타입 변환이 자바에 실장되어 있는 것이 가장 큰 차이점이라고 생각합니다.만약 당신이 이미 C에서 프로그래밍하는 것에 대해 상당히 편안함을 느끼고 있고, 직접 네이티브 코드를 구현해야 한다면, JNI는 그다지 복잡해 보이지 않을 것이라고 생각합니다.자바 프로그래머로 서드파티 네이티브라이브러리만 호출하면 되는 경우, JNI에서 그다지 명백하지 않은 문제를 피할 수 있는 가장 쉬운 방법은 아마도 JNI일 것입니다.
나는 어떤 차이도 벤치마킹한 적이 없지만 설계상 적어도 일부 상황에서 JNI보다 JNA와의 유형 변환이 더 좋지 않다고 가정할 것이다.예를 들어 어레이를 전달하면 각 함수 호출이 시작될 때 JNA가 Java에서 네이티브로 변환하고 함수 호출이 끝날 때 다시 변환합니다.JNI를 사용하면 어레이의 네이티브 "뷰"가 생성될 때 스스로 제어할 수 있습니다.어레이의 일부만 표시되도록 하고 여러 함수 호출에 걸쳐 보기를 유지하며 마지막에 보기를 릴리스하여 변경 내용을 유지할지(데이터를 다시 복사하지 않아도 됨)를 결정할 수 있습니다.메모리 클래스를 사용하여 여러 기능 호출에 걸쳐 네이티브 어레이를 사용할 수 있지만, 이 경우 메모리 복사가 필요하므로 JNI에서는 불필요할 수 있습니다.차이는 관련이 없을 수 있지만, 본래의 목표가 네이티브 코드로 애플리케이션의 일부를 실장함으로써 애플리케이션의 퍼포먼스를 향상시키는 것이라면, 퍼포먼스가 저하된 브리지 테크놀로지를 사용하는 것은 가장 확실한 선택은 아닌 것 같습니다.
- 당신은 몇 년 전에 유고 인민군이 존재하기 전에 코드를 작성했거나 1.4 이전 JRE를 목표로 하고 있습니다.
- 사용하고 있는 코드가 DLL\SO에 없습니다.
- LGPL과 호환되지 않는 코드를 작업하고 있습니다.
그것은 내가 쉽게 생각해 낼 수 있는 것 뿐이지만, 나는 어느 쪽도 헤비 유저는 아니다.또한 당신이 그들이 제공하는 인터페이스보다 더 나은 인터페이스를 원한다면 유고 인민군을 피할 수 있는 것처럼 보이지만 당신은 그것을 자바어로 코드화할 수 있다.
참고로, 저희 프로젝트 중 하나에서는 매우 작은 JNI 발자국을 남겼습니다.도메인 오브젝트를 나타내기 위해 프로토콜 버퍼를 사용했기 때문에 Java와 C를 브리지하기 위한 네이티브 함수는 하나뿐이었다(물론 C 함수는 다른 함수의 묶음을 호출한다).
이것은 직접적인 답변은 아니고, 저는 JNA에 대한 경험이 없지만, JNA를 사용한 프로젝트를 보고 SVNKit, IntelliJ IDEA, NetBeans IDE 등의 이름을 보면 꽤 괜찮은 도서관이라고 생각하는 경향이 있습니다.
사실 JNI보다 JNI가 더 간단해 보여야 할 때는 JNI 대신 JNI를 썼을 것 같다.유감입니다, 유고 인민군은 지금 석방되지 않았습니다.
JNI와 유고 인민군과의 간단한 벤치마크를 실시했습니다.
다른 사람들이 이미 지적했듯이, 유고 인민군은 편의를 위한 것이다.유고 인민군을 사용할 때 네이티브 코드를 컴파일하거나 작성할 필요가 없습니다. 유고 인민군의 네이티브 라이브러리 로더는 제가 본 것 중 가장 사용하기 쉽고 좋은 것 중 하나입니다.안타깝게도 JNI에서는 사용할 수 없는 것 같습니다.(그래서 JNA의 경로 규칙을 사용하여 클래스 패스(즉, jars)에서 심리스한 로드를 지원하는 System.loadLibrary()의 대안을 작성했습니다.
그러나 유고 인민군의 성과는 JNI의 성과보다 훨씬 더 나쁠 수 있다.나는 간단한 원어민 정수 증가 함수 "return arg + 1;"을 호출하는 매우 간단한 테스트를 만들었다.jmh를 사용한 벤치마크에서는 JNI가 JNA보다 15배 빠른 것으로 나타났다.
네이티브 함수가 4개의 값의 정수 배열을 합산한 더 "복잡한" 예에서도 JNI 성능이 JNA보다 3배 더 빠른 것으로 나타났다.JNI의 어레이에 액세스 하는 방법에 의한 메리트가 감소했을 가능성이 있습니다.이 예에서는, 몇개의 데이터를 작성해, 각 집계 조작시에 재차 릴리스 했습니다.
코드 및 테스트 결과는 github에서 확인할 수 있습니다.
JNI의 퍼포먼스를 필요로 하지만 그 복잡성에 굴하지 않는 경우에는 JNI 바인딩을 자동으로 생성하는 도구를 사용하는 것을 고려해 볼 수 있습니다.예를 들어 JANET(제소자:제가 작성했습니다)를 사용하면 Java와 C++ 코드를 하나의 소스 파일에 혼재시킬 수 있습니다.예를 들어 표준 Java 구문을 사용하여 C++에서 Java로 콜을 발신할 수 있습니다.예를 들어 C 문자열을 Java 표준 출력에 인쇄하는 방법은 다음과 같습니다.
native "C++" void printHello() {
const char* helloWorld = "Hello, World!";
`System.out.println(#$(helloWorld));`
}
그런 다음 JANET은 백틱 삽입 Java를 적절한 JNI 콜로 변환합니다.
JNI와 JNA의 퍼포먼스 비교를 위해 조사했습니다.프로젝트에서 dll을 호출하도록 이들 중 하나를 결정해야 하고 실시간 제약이 있었기 때문입니다.그 결과 JNI가 인민군(약 40배)보다 뛰어난 성과를 보였다.아마도 유고 인민군에서의 더 나은 성과를 위한 속임수가 있을지 모르지만 간단한 예로서는 매우 느리다.
내가 모르는 게 아니라면, JNA와 JNI의 가장 큰 차이점은 JNA에서는 자바 코드를 네이티브(C) 코드로 호출할 수 없다는 것 아닌가?
제 특정 어플리케이션에서는 JNI가 훨씬 사용하기 쉬웠습니다.시리얼 포트와의 연속 스트림을 읽고 쓸 필요가 있었습니다.그 외에는 아무것도 필요 없었습니다.JNA의 매우 복잡한 인프라스트럭처를 학습하기보다는 6가지 기능만 내보내는 특수 목적의 DLL을 사용하여 Windows의 네이티브 인터페이스를 프로토타입으로 만드는 것이 훨씬 쉽다는 것을 알게 되었습니다.
- DllMain(Windows와의 인터페이스에 필요)
- OnLoad (OutputDebugString만 실행하므로 Java 코드가 언제 연결되었는지 알 수 있습니다)
- 언로드 시(ditto)
- 열기(포트 열기, 읽기 및 쓰기 스레드 시작)
- Queue Message(쓰기 스레드에 의한 출력용으로 데이터를 큐잉)
- Get Message(마지막 콜 이후 읽은 스레드가 수신한 데이터를 대기 및 반환)
언급URL : https://stackoverflow.com/questions/1556421/use-jni-instead-of-jna-to-call-native-code
'source' 카테고리의 다른 글
HashTables는 충돌에 어떻게 대처합니까? (0) | 2022.12.18 |
---|---|
레코드를 단일 레코드로 선택하여 시간 차이를 확인하는 방법 (0) | 2022.12.18 |
LOCK TABLES가 테이블이 잠기지 않았다고 말한 후 UNION 쿼리에서 선택 (0) | 2022.12.18 |
jQuery의 .bind() 대 .on() (0) | 2022.12.08 |
cURL에서 $_POST 값 전달 (0) | 2022.12.08 |