2012-01-04 5 views
11

C++ ABI 호환성 문제로 인해 Java Native Interface (JNI)가 영향을 받습니까?C++ ABI 호환성 문제로 인해 Java Native Interface (JNI)가 영향을 받습니까?

Java 응용 프로그램을 개발 중입니다. Java Native Interface (JNI)를 사용하여 C++ 라이브러리의 함수를 호출하고 싶습니다. C++ 라이브러리의 코드에 액세스 할 수 있지만 필요한 경우 다시 작성할 수 있습니다. (예를 들어 정적으로 C++ 런타임을 연결할 수 있습니다.)

사용자가 JRE 6 이상을 요구할 수는 있지만 특정 C++ 런타임을 요구할 수는 없습니다.

동료가 동적으로로드 된 C++ 코드 사용을 권장하는이 블로그 기사 : http://www.trilithium.com/johan/2005/06/static-libstdc/을 알려주었습니다.

또 다른 동료가이 버그 보고서를 알려주었습니다 : http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4694590이 문제점이 Java 1.4.2에서 어떻게 해결되었는지 자세히 설명합니다.

문제의 요지는 이해할 수있는 것처럼 libstdC++의 바이너리 인터페이스가 자주 변경된다는 것입니다. C++ 응용 프로그램이 다른 컴파일러로 작성된 C++ 공유 라이브러리를로드하면 두 개의 호환되지 않는 libstdC++ 라이브러리가 동시에 메모리에로드됩니다.

버그 보고서는 Java 1.4.2의 해결책을 설명합니다 : "JDK에서 C++ 런타임을 정적으로 연결하고 링커 스크립트를 사용하여 libstdC++ 및 기타 내부 기호에서 기호를 숨길 수 있습니다. 결과적으로 이러한 기호는 JNI 코드에서 보이지 않게됩니다 일부 네이티브 코드가 C++ 런타임을 호출해야 할 때 적절한 libstdC++. so.로 호출됩니다. 두 개의 libstdC++.가 동시에로드되지만 양성이어야합니다. "

여기에 대해 몇 가지 질문이 있습니다.

먼저 OpenJDK가이 접근 방식을 계속 사용합니까?

[편집 :이 질문은 OpenJDK의 build-dev 메일 링리스트에서 질문했습니다. 핫 스폿은 여전히 ​​정적으로 libstdC++에 연결되지만, "대부분의 리눅스 배포판이이를 패치"합니다. " STATIC_CXX = false로 설정하면 충분합니다 (기본값은 true)."]

둘째로,이 경우에도 두 개의 호환되지 않는 libstdC++. 그래서 동시에로드됩니까?

셋째,이 접근법 (JDK의 기호 숨기기)은 모든 호환성 문제를 해결합니까?

위에서 언급 한 블로그 기사에서 "다른 ABI에 대해 컴파일 된 코드는 단순히 이진 호환이 아닙니다." 그리고 나중에 "언어 런타임 지원은 일반적으로 어떤 종류의 잠금 또는 전역 데이터 구조 (C 프로그램이 공유 된 errno를 필요로하는 것과 유사)에 액세스하기 위해 일부 데이터를 공유하는 데 의존합니다."

이렇게하면 문제를 해결할 수없는 것처럼 들립니다.

그런데 다시 ABI 비 호환성 문제는 더 이상 문제가되지 않습니다. 블로그 기사는 6 년이 넘었습니다. 또 다른 stackoverflow 질문 (GCC ABI compatibility)에 대한 하나의 대답은 "gcc-3.4.0부터 ABI는 앞으로 호환됩니다."라고 주장합니다. 그게 성공한거야?

이러한 문제에 대한 안내는 감사하겠습니다. (그리고 이봐,이 모든 것을 읽어 주셔서 감사합니다!)

내 질문은 꽤 오랫동안 얻고 있었다, 그래서 나는 모든 세부 사항을 제공하지 않았다

편집합니다. Will의 의견을 들으려면 :

  1. extern "C"기능 만 호출하면됩니다. (예를 들어 javah를 사용하여 C 헤더 파일을 생성합니다.)
  2. JVM에서 C++ 런타임과 상호 작용할 필요가 없습니다. (기본적으로 C++ 라이브러리에 문자열을 보내면됩니다.)

답변

5

잘 모르겠습니다. 그러나 그것은 결코 나를 멈추게하지 않았다.

먼저, 원하는 작업에 따라 다릅니다. JDK의 정적 링크의 전제는 실제 JDK 자체의 이식성을 향상시키는 것입니다. 사용자가 특정 OS에서 JDK를 다시 컴파일 할 것으로 예상 할 수 없기 때문에 최종 이진 파일을 이식 할 수있는 메커니즘이 필요했습니다. 명백하게 정적 링크가이 문제를 해결했습니다.

다음으로, JNI에 관해서는 먼저 C++이 아닌 C 함수를 호출하게 될 것입니다. JNI에 C++ 바인딩이있는 것은 아닙니다. 따라서, C++을 사용하고 싶다면 C 루틴으로 감싸서 Java와 대화해야합니다.

다음으로, 귀하의 C++ .so는 내가 상상하고있는 것처럼 정상적으로 OS에 동적으로 링크됩니다. JNI 루틴이 동적 인 .so와 동작하지 않을 것이라고 기대하는 것은 매우 까다 롭고 C++도 마찬가지입니다. 그리고 의심 할 여지없이 C++이 인기를 얻고 있음에도 불구하고 C++에 대해 동적으로 링크 할 수없는 것은 매우 가혹한 것처럼 보입니다. 그래서, 이것을 촉진하기 위해 일어날 필요가있는 속임수가 무엇이든간에, 그들은 (tm)이 이것을 가능하게하는 일을 수행했다는 합리적인 가정입니다.

그렇다면 C++이 Java 런타임의 C++ 런타임과 어떤 상호 작용을 할 것이라는 기대는 분명히 있어야합니다. 이상적으로, 그들은 단순히 평화롭게 공존 할 것입니다.

이렇게하면, C++은 동적으로 링크 될 것이고 설치된 OS의 설치된 C++ 런타임을 자비로 사용하기 때문에 ABI 이식성 문제가 발생할 것입니다.

결국 결국 나는 찢어지고 어떤 일이 벌어 지는지 보겠습니다.

+1

JNI에는 확실히 C++ 바인딩이 있습니다. 하지만 나는 C 바인딩의 헤더 전용 래퍼를 의심하므로 ABI 문제에 면역이되어야합니다. –