Переписать код C на Java или использовать JNI? - PullRequest
18 голосов
/ 04 марта 2009

В настоящее время я работаю над проектом, написанным на Java. У нас есть несколько алгоритмов, написанных на C / C ++ (по крайней мере, пара сотен), которые необходимо включить в наш проект. Наши два варианта - использовать JNI для вызова этого кода или переписать все алгоритмы на Java.

Я знаю о последствиях использования JNI, это может открыть целый ряд новых проблем, поэтому переписывание всего кода на Java даже рассматривается. Но мысль о переписывании кажется ... неправильной. Алгоритмы были проверены и работают, насколько я знаю, они просто не на том языке.

В этой ситуации JNI облегчит эту задачу? Или это вызовет больше головной боли, чем переписывание кода на Java?


РЕДАКТИРОВАНИЕ № 1: Смежный вопрос - Полезность JNI


РЕДАКТИРОВАТЬ # 2: К вашему сведению - наш Java-проект никоим образом не предназначен для переноса. Это может устранить один из недостатков JNI в том, что он предположительно снижает мобильность.

Ответы [ 11 ]

18 голосов
/ 04 марта 2009

Простой ответ: если код будет много называться, а производительность важна, то конвертируйте его в Java.

Более сложные ответы:

  • если библиотека легко упакована в JNI, тогда используйте JNI
  • если тесты для кода C / C ++ легко конвертируются в Java, перейдите к порту

Я бы сделал следующее:

  • возьмите один из алгоритмов и оберните его в JNI
  • взять тот же алгоритм и преобразовать его в Java
  • смотри, что еще труднее сделать
  • если скорость имеет значение, профилируйте обе версии и посмотрите, какая из них приемлема.
14 голосов
/ 04 марта 2009

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

13 голосов
/ 04 марта 2009

Если «алгоритмы» хорошо упакованы, возможно, возможно создать какой-нибудь автоматический клейкий код через JNI? Это уменьшит риск ошибок (создание сотен отдельных компонентов вручную кажется рискованным) и сделает стоимость более или менее независимой от количества добавляемых алгоритмов.

Переписывание сотен компонентов звучит очень рискованно, я бы определенно рекомендовал, по крайней мере, сначала изучить JNI более внимательно.

Какие требования к вводу / выводу предъявляют алгоритмы к остальной части проекта? Если они довольно слабо связаны, возможно, было бы возможно запустить их как отдельные программы, вызываемые как подпроцессы из Java и использующие, например, stdio для обмена данными?

9 голосов
/ 05 марта 2009

Я думаю, вы обнаружите, что использование JNI не так сложно, как кажется до погружения. Есть некоторые важные компромиссы и ограничения, но в целом JNI работает хорошо, и его достаточно легко использовать, как вы и предполагали.

Как уже говорили другие, лучший случай для JNI:

  • Сложный нативный код (бонусные баллы, если этот код уже оказался очень надежным)
  • Минимальный возврат туда-сюда между Java и собственным кодом (вы хотите минимизировать количество обращений через уровень JNI)
  • Достаточно простой интерфейс вызова нативного кода (или также обратно в Java, если ваш нативный код должен использовать объекты / методы Java)

Определенно возможно автоматизировать или псевдоавтоматизировать создание слоя JNI для разумно структурированного набора собственных компонентов. Это будет стоить того, если количество компонентов для упаковки велико.

Хорошей новостью с JNI является то, что вам будет легко создать и протестировать этот интерфейс, например, вы должны быть в состоянии написать тестовые случаи из Java, которые используют поведение существующего алгоритма, и если есть проблемы, они, скорее всего, будут в самом слое JNI, а не в алгоритмах (учитывая вашу уверенность в нативной реализации).

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

И последнее соображение - будущая жизнь этих алгоритмов или связанных с ними компонентов. Набор алгоритмов более или менее полон, или вы продолжаете добавлять? В любом случае, существует ли серьезная причина для технического обслуживания и / или дальнейшего развития, чтобы отдать предпочтение одной технологии над другой? Например, если все остальное в Java и все новые алгоритмы будут в Java, и почти все в команде почти всегда программируют на Java, повторное выполнение на Java начинает выглядеть более привлекательным в долгосрочной перспективе.

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

8 голосов
/ 04 марта 2009

Если вы планируете писать будущие проекты на Java, в отличие от C / C ++. Я бы сейчас прикусил пулю и перенес код на java. Чем дольше вы будете ждать, тем хуже станет. В этом случае JNI звучит привлекательно, но тогда у вас возникнет проблема, когда кому-то придется поддерживать код C ++, когда все остальные заняты новыми забавными Java-проектами.

Если это разовый Java-проект, то почему вы пишете его на Java?

8 голосов
/ 04 марта 2009

Я бы все еще серьезно подумал о переходе на JNI, особенно если вы можете минимизировать количество межъязыковых интерфейсов.

Если, например, есть целый стек функций C, которые имеют одинаковые входы и выходы, но выполняют разную работу над входами, оберните это в одну оболочку JNI с дополнительным параметром, чтобы указать, какой конкретный алгоритм использовать.

3 голосов
/ 04 марта 2009

Мост между C и Java стоит дорого, поэтому, если вам придется передавать много данных назад и вперед, выиграть вызов C через JNI невозможно.

Я видел в списке JNA разумную альтернативу JNI с гораздо меньшими трудностями при вызове методов в DLL / разделяемой библиотеке из Java в отраженном смысле. Я еще не пробовал.

Возможно, вы захотите рассмотреть компиляцию своего кода C в виде двоичного файла MIPS для Linux, который можно интерпретировать на Java. Достаточно быстро, немного сложно правильно настроить. Смотри http://nestedvm.ibex.org/

Также вы можете использовать бэкэнд llvm для gcc для компиляции в низкоуровневые байт-коды, которые затем можно интерпретировать в Java. Это также подход, который используется с iPhone SDK на Mac OS X. http://llvm.org/

2 голосов
/ 21 апреля 2009

Я был в такой ситуации. Я предлагаю вам привыкнуть к использованию многопоточных структур данных, доступных в Java. На этом этапе вы больше не захотите возвращаться к своим структурам данных C ++.

Вы также поймете, что вы можете гораздо лучше переписать эти алгоритмы, используя более продуманные методы, лучший полиморфизм, шаблоны адаптеров и т. Д.

Когда вы сидите в коде C / C ++, вы думаете, что хотите его придерживаться. Вы думаете обо всей любви, которую вкладываете в это. Через несколько лет вы поймете, что, удерживая его и используя JNI, вы создали монстра. Каждый раз, когда вы получаете сбой процесса, вы будете сожалеть об использовании JNI. После исправления сбоя процесса кто-то захочет изменить алгоритм в C ++, и вам захочется их ограничить. У них будет удобное оправдание: «Я еще не привык к Java».

Взгляните на неизменные структуры данных в Java. Даже не думайте о скорости, которую выполняют эти старые алгоритмы C / C ++. Я обнаружил, что мой новый код намного превосходит любой мой старый код C / C ++.

Написать юнит-тесты. Используйте NetBeans.

С уважением,

-Stosh

2 голосов
/ 04 марта 2009

Прочтите сообщение Джоэла о " Погашении вашего технического долга ", затем переходите сейчас и конвертируйте его сейчас, а не выплачивайте проценты в течение следующих нескольких лет, а затем выплачивайте.

Возможно, перепакованные библиотеки могут быть полезны и в других местах. Если они полезны и достаточно сложны, чтобы заставить вас задуматься о том, чтобы хранить их в C, они должны иметь еще больше возможностей после того, как они красиво упакованы в многократно используемые, легко распространяемые и понятные классы.

1 голос
/ 04 марта 2009

Дайте JNI попробовать. Затем, если возникнут какие-либо проблемы, вы можете переписать проблемные или обернуть вызовы JNI веб-сервисами и развернуть их на разных или виртуальных блоках.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...