Подвержен ли Java Native Interface (JNI) проблемам совместимости C ++ ABI?

Подвержен ли Java Native Interface (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 придерживаться этого подхода?

[РЕДАКТИРОВАТЬ: Я задал этот вопрос в списке рассылки OpenJDK build-dev. Ответ - да, 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 ++.)

person John V.    schedule 04.01.2012    source источник


Ответы (1)


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

Во-первых, это зависит от того, чем вы хотите заниматься. Предпосылка статического связывания 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 ++ среды выполнения.

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

person Will Hartung    schedule 04.01.2012
comment
JNI, безусловно, имеет привязку к C ++. Но я подозреваю, что это оболочка только для заголовка привязки C, поэтому она должна быть защищена от проблем с ABI. - person Michael Anderson; 04.01.2012