Дмитрий рассказал о преимуществах, недостатках и основных сценариях использования нативного кода при написании кроссплатформенных приложений. Спикер рассказывает о разнообразных подводных камнях, которые неизбежно возникают при работе с NDK, и показывает интересные хаки и неочевидные возможности решения возникающих проблем.
Мир глазами нейросетей, Данила Байгушев, Александр Сноркин ()
Дмитрий Юницкий. «Android NDK или как я перестал бояться и полюбил нативную разработку».
1. Android NDK, или как я
перестал бояться и полюбил
нативную разработку.
2. Android NDK.
• JNI - набор инструментов для запуска кода на C/
C++/Ассемблере из виртуальной машины Java
• Вспомогательная нативная
библиотека(скомпилированная для каждой
поддерживаемой ABI) или полностью нативное
приложение используя NativeActivity
• Java -> нативный код, нативный код -> Java, Java
-> нативный код -> Java…
3. Зачем?
• Критичные по производительности участки кода
• Использование написанного ранее кода или
существующих библиотек (OpenCV, ffmpeg, …)
• Написание кроссплатформенного кода для
нескольких платформ(бизнес-логика, алгоритмы
и тд)
4. Какие возникают
сложности?
• Работа с jni из нативных потоков
• Отладка
• Возрастающий размер результирующей apk
• Локальные/глобальные ссылки
• Дорогой переход из java кода в нативный
(и обратно)
• Прочие приятные сюрпризы от jni)
8. Локальные и глобальные
ссылки.
• Объекты, на которые есть ссылки - не могут быть очищены
GC
• Локальные ссылки - в пределах жизни метода в рамках
одного потока
• Java VM автоматически очищает ссылки при возврате из
нативного метода
• Есть предел на количество создаваемых локальных ссылок
• Глобальные ссылки действительны вплоть до явного
освобождения
10. Нативные потоки.
• AttachCurrentThread для работы с jni
• DetachCurrentThread перед завершением
• Локальные ссылки НЕ очищаются - нужно
всегда(!) очищать все созданные ссылки с
помощью DeleteLocalRef либо создавать
отдельный пул ссылок при входе в метод через
PushLocalFrame/PopLocalFrame
• FindClass НЕ работает
13. Кеширование jClass,
jMethodId, jFieldId.• jClass -локальные ссылки, для кеширования
необходимо преобразовывать в глобальные.
• jMethodId, jFieldId - просто структуры, можно
записывать без преобразования в статические
или глобальные переменные и использовать в
любых потоках.
14. Кеширование jClass,
jMethodId, jFieldId.• jClass -локальные ссылки, для кеширования
необходимо преобразовывать в глобальные.
• jMethodId, jFieldId - просто структуры, можно
записывать без преобразования в статические
или глобальные переменные и использовать в
любых потоках.
• В некоторых случаях работа через jni может быть
ЗНАЧИТЕЛЬНО медленнее аналогичного кода на
Java.
15. Запуск native метода из
Java.
• Создать новый стекфрейм
• Передать аргументы согласно ABI
• Передать JNIEnv* и jclass(jobject)
• Synchronized
• Проверить исключения
• …
16. Сборка проекта. Как было
раньше.
• MAKEFILES
• Javah
• SWIG
• Ecplise plugin Sequoyah
• …