Java에서 JNI 호출을 할 때 ‘교차 경계’가 느리다는 것을 알고 있습니다.
그러나 느리게 만드는 것이 무엇인지 알고 싶습니다 . JNI 호출을 수행 할 때 기본 jvm 구현이 느리게 만드는 것은 무엇입니까?
답변
먼저, “느리게”함으로써 수십 나노초가 걸릴 수있는 것에 대해 이야기하고 있습니다. 사소한 기본 방법의 경우 2010 년에 Windows 데스크톱에서 평균 40ns, Mac 데스크톱에서 11ns의 통화를 측정했습니다. 전화 를 많이 하지 않으면 눈치 채지 못할 것입니다.
즉, 기본 메소드 호출 은 일반 Java 메소드 호출보다 느릴 수 있습니다 . 원인은 다음과 같습니다.
- 기본 메소드는 JVM에 의해 인라인되지 않습니다. 이 특정 머신에 대해 적시에 컴파일되지도 않으며 이미 컴파일되어 있습니다.
- Java 배열은 원시 코드로 액세스하기 위해 복사 한 후 나중에 다시 복사 할 수 있습니다. 비용은 어레이 크기에서 선형 일 수 있습니다. Windows 데스크톱에서는 평균 약 75 마이크로 초, Mac에서는 82 마이크로 초로 100,000 어레이의 JNI 복사 를 측정했습니다 . 다행히도 직접 액세스는 GetPrimitiveArrayCritical 또는 NewDirectByteBuffer 를 통해 얻을 수 있습니다 .
- 메소드에 객체가 전달되거나 콜백이 필요한 경우 기본 메소드가 JVM을 자체적으로 호출합니다. 원시 코드에서 Java 필드, 메소드 및 유형에 액세스하려면 리플렉션과 유사한 것이 필요합니다. 서명은 문자열로 지정되고 JVM에서 쿼리됩니다. 이 느린 둘 다 와 오류가 발생하기 쉬운.
- Java 문자열은 객체이며 길이가 있으며 인코딩됩니다. 문자열에 액세스하거나 문자열을 작성하려면 O (n) 사본이 필요할 수 있습니다.
날짜에 대한 추가 논의는 “9.2 : JNI 비용 조사”의 Steve Wilson과 Jeff Kesselman의 “Java 플랫폼 성능 : 전략 및 전술”(2000)에서 찾을 수 있습니다. 아래 @Philip의 의견에 제공된 이 페이지 의 1/3 정도입니다 .
2009 IBM developerWorks 백서 “Java Native Interface 사용을위한 우수 사례” 에서는 JNI의 성능 저하를 피하는 방법에 대한 제안을 제공합니다.
답변
표시된 모든 Java 메소드 native
가 “느리게” 있는 것은 아닙니다 . 그들 중 일부는 본질적으로 매우 빠릅니다. 고유하고 사람이되지 않는, 당신이 볼 수있는 사람을 확인하려면 do_intrinsic
에서 vmSymbols.hpp .