Влияет ли на собственный интерфейс Java (JNI) проблема совместимости с C ++ ABI? - PullRequest
12 голосов
/ 04 января 2012

Влияет ли на собственный интерфейс Java (JNI) проблема совместимости с C ++ ABI?

Я занимаюсь разработкой приложения на Java.Я хотел бы использовать собственный интерфейс Java (JNI) для вызова функций в библиотеке C ++.У меня есть доступ к коду для библиотеки C ++, и я могу перестроить его, однако мне может понадобиться.(Например, я могу статически связать среду выполнения C ++.)

Я могу требовать, чтобы у моих пользователей была JRE 6 или выше, но я не могу требовать, чтобы у них была какая-то конкретная среда выполнения C ++.

Сотрудник указал мне на эту статью в блоге: http://www.trilithium.com/johan/2005/06/static-libstdc/, в которой не рекомендуется использовать динамически загружаемый код C ++.

Другой сотрудник указал мне на этот отчет об ошибке: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4694590, который подробно описывает, как этипроблемы были устранены в Java 1.4.2.

Суть проблемы, насколько я понимаю, заключается в том, что двоичный интерфейс libstdc ++ часто изменяется.Если приложение C ++ загружает разделяемую библиотеку C ++, созданную с помощью другого компилятора, две несовместимые библиотеки libstdc ++ будут загружены в память одновременно.

В отчете об ошибке объясняется решение для Java 1.4.2: "Мы статически связываем среду выполнения C ++ в JDK и включаем скрипт компоновщика, чтобы скрыть символы от libstdc ++ и других внутренних символов. В результате эти символы становятся невидимыми для кода JNI, и когда некоторый нативный код должен вызываться во время выполнения C ++, вызов будетрешена с помощью соответствующей библиотеки libstdc ++. итак. Есть еще два libstdc ++., поэтому загружаются одновременно, но это должно быть мягко. "

У меня есть несколько вопросов по этому поводу.

СначалаOpenJDK продолжает использовать этот подход?

[ EDIT: Я задал этот вопрос в списке рассылки для разработчиков OpenJDK.Ответ - да, HotSpot все еще статически связывает libstdc ++, но, очевидно, «большинство дистрибутивов Linux исправляют это».Другой разработчик отмечает, что для этого даже не требуется патч: «Достаточно установить STATIC_CXX = false (по умолчанию true).»]

Во-вторых, даже в этом случае действительно удобно иметь дванесовместимый libstdc ++. так загружен одновременно?

В-третьих, решает ли этот подход (чтобы скрыть символы в JDK) все проблемы совместимости?

В статье блога, упомянутой выше, предупреждает, что«код, скомпилированный для разных ABI, просто не совместим двоично».И позже, что «поддержка языковой среды выполнения обычно полагается на некоторые данные, которые используются совместно, например, для доступа к какой-либо блокировке или глобальной структуре данных (аналогично тому, как программам на C требуется общий номер ошибки)».

Это делает егоПохоже, проблема не может быть решена.

Опять же, возможно, несовместимость ABI больше не является проблемой.Статья в блоге старше шести лет.Один ответ на другой вопрос stackoverflow ( GCC ABI совместимость ) утверждает, что «Начиная с gcc-3.4.0, ABI совместим с прямой совместимостью».Это было успешно?

Буду признателен за любые рекомендации по этим вопросам.(И, эй, спасибо, что прочитали все это!)

РЕДАКТИРОВАТЬ

Мой вопрос становился довольно длинным, поэтому я не дал всех подробностей.Чтобы ответить на комментарии Уилла:

  1. Мне нужно только вызвать внешние функции "C".(Например, я использую javah для генерации файла заголовка C.)
  2. Мне не нужно взаимодействовать со средой выполнения C ++ в JVM.(Мне просто нужно отправить строки в библиотеку C ++.)

1 Ответ

5 голосов
/ 04 января 2012

Я не знаю.Но это никогда не останавливало меня.

Во-первых, это зависит от того, что вы хотите сделать.Предпосылка статического связывания JDK заключается в улучшении переносимости самого JDK.Поскольку они не могут ожидать, что пользователи будут перекомпилировать JDK в своей конкретной ОС, им нужен механизм, чтобы сделать финальный двоичный файл переносимым.Очевидно, статическое связывание решило эту проблему.

Далее, что касается JNI, сначала вы будете вызывать функции C, а не C ++, я не верю, что JNI имеет какую-либо привязку C ++.Итак, какой бы C ++ вы ни захотели использовать, он должен быть обернут в подпрограмму C для общения с Java.

Затем ваш C ++ .so будет динамически связываться с ОС, почти как обычно, я предполагаю,Кажется довольно драконовским ожидать, что подпрограмма JNI не будет работать с динамически связанным .so, и C ++ .so не должен отличаться.И, без сомнения, C ++ так же популярен, как и сейчас, и похоже на то, что вы не сможете динамически связываться с C ++ .so.Таким образом, независимо от того, какие махинации должны были иметь место, чтобы облегчить это, разумно предположить, что Они (тм) сделали работу, чтобы это произошло.

Тем не менее, не должно быть никаких ожиданийИспользуемый вами C ++ будет иметь какое-либо взаимодействие со средой выполнения C ++ во время выполнения Java.В идеале они будут просто мирно сосуществовать.

Учитывая, что, если это вообще работает, ваш C ++ наверняка будет иметь проблему переносимости ABI, поскольку он будет динамически связываться и будет зависеть от установленной ОС C ++ во время выполнения.

Итак, в конце концов, я просто разорвал его и посмотрел, что произойдет.

...