SlideShare a Scribd company logo
Android NDK & JNI
Использование Java Native Interface (JNI) и
кросплатформенных C/C++ реализаций в Java (Android)
Sergey Komlach
GDG Kremenchuk, StickyPassword
Skype: s.komlach
sergey.komlach@stickypassword.com
● Что такое JNI/NDK? Быстродействие, много готовых либ, платформозависимость, не-
"Write once, run anywhere" (WORA), аналогия с Reflection, используемые типы и вызовы
● Настройка окружения (NDK x 2), отладка, поддержка и тестирование всех платформ
● Пример простейшей реализации Java → C.
● Вызов из С++ метода Java как колбека (Java interface)
● Особенности выполнения кода (BlackBerry10 (mktime()), IntelAtom, х64), tmpdir(), флаги
оптимизации, порезаный Bionic и прочие либы в Андроид, удаление SO-шек на Sony при
апдейте
Рассмотрим….
Wiki: Java Native Interface (JNI) — стандартный механизм для запуска кода, под управлением
виртуальной машины Java (JVM), который написан на языках С/С++ или Ассемблера, и
скомпонован в виде динамических библиотек, позволяет не использовать статическое
связывание. Это даёт возможность вызова функции С/С++ из программы на Java, и наоборот.
Более ранние интерфейсы, в отличие от JNI, не удовлетворяли условию двоичной
совместимости.
Wiki: В 2009 году в дополнение к ADT был опубликован Android Native Development Kit (NDK) —
пакет инструментариев и библиотек, позволяющий реализовать часть приложения на языке
С/С++. NDK рекомендуется использовать для разработки участков кода, критичных к скорости.
Реально же наиболее частое применение:
Работа с OpenGL ES
Использование кросс-платформенных игровых движков, например Cocos2Dx
Использование уже написанного на C/C++ кода (а его ох как дофига написано!). Часто, это
работа с мультимедиа, например FFMPEG, libpng или наукоемкие вещи типа openCV
«Обход» «бутылочного горлышка» в программе (UP! «тяжелых» процессов)
Кроссплатформенное (повторное) использование кода
JNI/NDK
Работа с NDK на порядок усложняет разработку.
- Разработчик должен понимать Java (само собой)
- С/С++ (особенно внимание на память, указатели, треды/семафоры и т.д)
- команды и принципы работы JVM (очень пригодится если вы уже работали с Reflection)
Class cls = sample1.getClass();
try {
cls.getDeclaredMethod("print", String.class).invoke(sample1, "sample class");
cls.getDeclaredMethod("print", String.class).invoke(sample1, "test string");
cls.getDeclaredMethod("print", null).invoke(sample2, null);
cls.getDeclaredMethod("print", null).invoke(sample3, null);
} catch (Exception e) {}
- Нужно учитывать большое количество ограничений JNI в Android (порезаные библиотека,
размеры типов, «пустышки» реализаций)
- Сложная настройка среды и особенно отладка
Таким образом, работа с NDK чаще всего представляем из себя процесс (часто — мучительный)
сборки некой библиотеки и написиние оберток (wrappers) на нативные методы. В тоже время,
сейчас есть возможность ваять приложение практически без использования Java, используя
NativeActivity (API 9 и выше).
package com.example;
public class NativeTest{
static {
System.loadLibrary("nativetest"); // libs/armeabi-v7a/libnativetest.so
}
public native boolean testMethod(int arg);
}
JNIEXPORT jboolean JNICALL Java_com_example_NativeTest_testMethod
(JNIEnv *env, jobject caller, jint arg);
JNIEXPORT — необходимый для JNI модификатор. Типы данных с префиксом «j»: jdouble,
jobject, jstring etc — это «отражения» объектов и типов Java в C/C++.
Именование
jstring JAVA_JNI_This_1Is_1Native_00024Wrapper_00024_000408_000413_000397(...)
Дело в том, что _1 это аналог нижнего подчёркивания.
_00024 это символ $, то есть может как разделитель внутреннего класса использоваться.
_00408, 0xxxx, это код в юникоде.
В итоге получается:
class JNI {
static class This_Is_Native {
static class Wrapper$ {
static String Юникод(...)
}
Именование, часть 2
Java JNI JNI array Code Array Code
boolean jboolean jbooleanArray Z [Z
byte jbyte jbyteArray B [B
char jchar jcharArray C [C
double jdouble jdoubleArray D [D
float jfloat jfloatArray F [F
int jint jintArray I [I
long jlong jlongArray J [J
short jshort jshortArray S [S
Object/Class/
String
jobject/jclass/
jstring
jobjectArray/-/- L/L/L [L/[L/[L
void void - V -
Внутренности JNI в Android
● Устаналивается APK
● Если внутри находятся SO-файлы (аналог DLL) они копируются в
/data/data/apppackage/app_lib/*.so
● При первом обращении к классу, использующему нативные библиотеки, последние
загружаются через System.load(«name»)
● Библиотека «живет» пока не будет завершено приложение
Как работает взаимодействие
между Java и Native
● Качаем NDK. При чем если хотим все платформы, то нужно NDK x32 (для arm6, arm7a, x86
& mips) и NDK x64 (arm8, x86_64 & mips_64 и все х32)
● Устанавливаем окружение
(путь к папке NDK)
● «цепляем» в IDE
С чего начинается NDK
javah создает файлы заголовков и исходники C из Java класса.
Эти файлы обеспечивают связь, которая позволит взаимодействовать вашему Java и C коду
javah -classpath bin/classes -jni -d jni com.my.javaclass
javah
Application.mk
APP_PLATFORM := android-9
APP_STL := stlport_static
APP_ABI := all32
APP_CPPFLAGS += -std=c++11
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_CPP_FEATURES += rtti # Enable exceptions in Android.mk
LOCAL_CPP_FEATURES += exceptions # Enable exceptions in Android.mk
LOCAL_LDLIBS := -llog -lz
LOCAL_MODULE := nativeTest
LOCAL_CFLAGS := -DANDROID -O3 -pipe
LOCAL_CXXFLAGS := -DANDROID -O3 -pipe
LOCAL_SRC_FILES :=com_test.cpp
Android.mk & Application.mk
Использование Java Native Interface (JNI) и кросплатформенных C/C++ реализаций в Java/Android
- Логгирование
__android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
- StackTrace в LogCat
Dalvik:
F/libc (17861): invalid address or address of corrupt block 0x7f51ce50 passed to dlfree
F/libc (17861): Fatal signal 11 (SIGSEGV) at 0xdeadbaad (code=1), thread 29266 (Thread-9488)
ART:
A/art(21149): sart/runtime/check_jni.cc:65] JNI DETECTED ERROR IN APPLICATION: input is not valid Modified UTF-8: illegal
start byte 0xa3
….
A/art(21149): sart/runtime/check_jni.cc:65] native: #07 pc 000bfaad /system/lib/libart.so (art::CheckJNI::NewStringUTF
(_JNIEnv*, char const*)+44)
A/art(21149): sart/runtime/check_jni.cc:65] native: #08 pc 00008fbb /data/app/com.stickypassword.android-
1/lib/arm/libSPCAgent.so (setValue(_jobject*, int, long, char*, char*)+202)
A/art(21149): sart/runtime/check_jni.cc:65] native: #09 pc 00009ac7 /data/app/com.stickypassword.android-
1/lib/arm/libSPCAgent.so (Java_com_spc_SPCManager_GetAuthCredentialsV2+82)
Отладка
GDB (GNU Debugger) — переносимый отладчик проекта GNU, который работает на многих UNIX-
подобных системах и умеет производить отладку многих языков программирования, включая
Си, C++, Free Pascal, FreeBASIC, Ada и Фортран. GDB — свободное программное обеспечение,
распространяемое по лицензии GPL.
GDB
package com.example.testsimplycall;
public class NativeTest {
static {
try{
// == Runtime.getRuntime().loadLibrary("testSimplyCall");
System.loadLibrary("testSimplyCall");
} catch (UnsatisfiedLinkError err){
//need catch exception
err.printStackTrace();
}
}
public native void testMePlz(String msg);
}
project/jni/com_example_testsimplycall_NativeTest.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
#ifndef _Included_com_example_testsimplycall_NativeTest
#define _Included_com_example_testsimplycall_NativeTest
#ifdef __cplusplus
extern "C" {
#endif
JNIEXPORT void JNICALL Java_com_example_testsimplycall_NativeTest_testMePlz(JNIEnv *env,jobject jobj, jstring msg);
#ifdef __cplusplus
}
#endif
#endif
project/jni/com_example_testsimplycall_NativeTest.cpp
#include <def.h>
#include <jni.h>
#include "com_example_testsimplycall_NativeTest.h"
JNIEXPORT void JNICALL Java_com_example_testsimplycall_NativeTest_testMePlz(JNIEnv *env,
jobject jobj, jstring msg){
jboolean isCopy;
const char * Str;
Str = env->GetStringUTFChars(msg, &isCopy);
LOGI("string = "%s"",Str);
}
package com.example.testcallback;
import android.util.Log;
public interface NativeCallback {
public void print(String str);
}
public class NativeTest {
static {
try{
System.loadLibrary("testCallback");
} catch (UnsatisfiedLinkError err){
err.printStackTrace();
}
}
public NativeCallback nativecallback = new NativeCallback(){
@Override
public void print(String str) {
Log.d("JAVA_CALLBACK", str);
}};
public native void testMePlz(String msg);
public native void SetListener(NativeCallback javacallback);
}
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
#ifndef _Included_com_example_testcallback_NativeTest
#define _Included_com_example_testcallback_NativeTest
#ifdef __cplusplus
extern "C" {
#endif
JNIEXPORT void JNICALL Java_com_example_testcallback_NativeTest_testMePlz(JNIEnv *env,
jobject jobj, jstring msg);
JNIEXPORT void JNICALL Java_com_example_testcallback_NativeTest_SetListener(
JNIEnv *env, jobject jobj, jobject callback);
#ifdef __cplusplus
}
#endif
#endif
#include <jni.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "com_example_testcallback_NativeTest.h"
jobject javaCallback;
JavaVM* mJVM;
/* Reference to Java-object*/
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved)
{
mJVM = jvm;
return JNI_VERSION_1_2;
}
JNIEnv* getJniEnv() {
JavaVMAttachArgs attachArgs;
attachArgs.version = JNI_VERSION_1_2;
attachArgs.name = ">>>NativeThread__Any";
attachArgs.group = NULL;
JNIEnv* env;
if (mJVM->AttachCurrentThread(&env, &attachArgs) != JNI_OK) {
env = NULL;
}
return env;
}
void printToLogcat(const char* msg) {
JNIEnv* pEnv = getJniEnv();
jclass javaClass = pEnv->GetObjectClass(javaCallback);
if (javaClass != NULL) {
jmethodID javaMethodID = pEnv->GetMethodID(javaClass, "print","(Ljava/lang/String;)V");
jstring logmsg = pEnv->NewStringUTF(msg);
if (logmsg != NULL) {
pEnv->CallVoidMethod(javaCallback, javaMethodID, logmsg);
pEnv->DeleteLocalRef(logmsg);
logmsg = NULL;
}
pEnv->DeleteLocalRef(javaClass);
javaClass = NULL;
}
}
JNIEXPORT void JNICALL Java_com_example_testcallback_NativeTest_SetListener(
JNIEnv *env, jobject jobj, jobject callback) {
if(javaCallback)
env->DeleteGlobalRef(javaCallback);
javaCallback = env->NewGlobalRef(callback);
}
JNIEXPORT void JNICALL Java_com_example_testcallback_NativeTest_testMePlz(JNIEnv *env,jobject jobj, jstring msg){
jboolean isCopy;
const char * Str;
Str = env->GetStringUTFChars(msg, &isCopy);
printToLogcat(Str);
}
● Blackberry10 (mktime)
● ARM & Intel
● NDK X32 & х64
● Android L & 5.0 (копирование массивов)
● tmpdir()/tmpfile()
● флаги оптимизации ( -03,-Ofast, -SSE etc)
● порезаный Bionic и прочие либы в Андроид
● *.so на Sony
● Проблема 01.01.2037
Грабли
Android NDK & JNI
Использование Java Native Interface (JNI) и
кросплатформенных C/C++ реализаций в Java (Android)
Q/A
Sergey Komlach
GDG Kremenchuk, StickyPassword
Skype: s.komlach
sergey.komlach@stickypassword.com
Ad

More Related Content

What's hot (20)

Разница в подходах анализа кода компилятором и выделенным инструментом
Разница в подходах анализа кода компилятором и выделенным инструментомРазница в подходах анализа кода компилятором и выделенным инструментом
Разница в подходах анализа кода компилятором и выделенным инструментом
Tatyanazaxarova
 
C++ STL & Qt. Занятие 08.
C++ STL & Qt. Занятие 08.C++ STL & Qt. Занятие 08.
C++ STL & Qt. Занятие 08.
Igor Shkulipa
 
C++ STL & Qt. Занятие 05.
C++ STL & Qt. Занятие 05.C++ STL & Qt. Занятие 05.
C++ STL & Qt. Занятие 05.
Igor Shkulipa
 
C++ весна 2014 лекция 5
C++ весна 2014 лекция 5C++ весна 2014 лекция 5
C++ весна 2014 лекция 5
Technopark
 
C++ STL & Qt. Занятие 01.
C++ STL & Qt. Занятие 01.C++ STL & Qt. Занятие 01.
C++ STL & Qt. Занятие 01.
Igor Shkulipa
 
C++ STL & Qt. Занятие 06.
C++ STL & Qt. Занятие 06.C++ STL & Qt. Занятие 06.
C++ STL & Qt. Занятие 06.
Igor Shkulipa
 
C++ STL & Qt. Занятие 02.
C++ STL & Qt. Занятие 02.C++ STL & Qt. Занятие 02.
C++ STL & Qt. Занятие 02.
Igor Shkulipa
 
Память в Java. Garbage Collector
Память в Java. Garbage CollectorПамять в Java. Garbage Collector
Память в Java. Garbage Collector
Olexandra Dmytrenko
 
Шишки, набитые за 15 лет использования акторов в C++
Шишки, набитые за 15 лет использования акторов в C++Шишки, набитые за 15 лет использования акторов в C++
Шишки, набитые за 15 лет использования акторов в C++
Yauheni Akhotnikau
 
C++ осень 2013 лекция 4
C++ осень 2013 лекция 4C++ осень 2013 лекция 4
C++ осень 2013 лекция 4
Technopark
 
C++ осень 2013 лекция 9
C++ осень 2013 лекция 9C++ осень 2013 лекция 9
C++ осень 2013 лекция 9
Technopark
 
Современный статический анализ кода: что умеет он, чего не умели линтеры
Современный статический анализ кода: что умеет он, чего не умели линтерыСовременный статический анализ кода: что умеет он, чего не умели линтеры
Современный статический анализ кода: что умеет он, чего не умели линтеры
corehard_by
 
C++ осень 2013 лекция 7
C++ осень 2013 лекция 7C++ осень 2013 лекция 7
C++ осень 2013 лекция 7
Technopark
 
C++ refelection and cats
C++ refelection and catsC++ refelection and cats
C++ refelection and cats
corehard_by
 
Александр Фокин, Рефлексия в C++
Александр Фокин, Рефлексия в C++Александр Фокин, Рефлексия в C++
Александр Фокин, Рефлексия в C++
Sergey Platonov
 
Зачем нужна Scala?
Зачем нужна Scala?Зачем нужна Scala?
Зачем нужна Scala?
Vasil Remeniuk
 
SAST и Application Security: как бороться с уязвимостями в коде
SAST и Application Security: как бороться с уязвимостями в кодеSAST и Application Security: как бороться с уязвимостями в коде
SAST и Application Security: как бороться с уязвимостями в коде
Andrey Karpov
 
Java: вчера, сегодня, завтра
Java: вчера, сегодня, завтраJava: вчера, сегодня, завтра
Java: вчера, сегодня, завтра
Леонид Ставила
 
Разница в подходах анализа кода компилятором и выделенным инструментом
Разница в подходах анализа кода компилятором и выделенным инструментомРазница в подходах анализа кода компилятором и выделенным инструментом
Разница в подходах анализа кода компилятором и выделенным инструментом
Tatyanazaxarova
 
C++ STL & Qt. Занятие 08.
C++ STL & Qt. Занятие 08.C++ STL & Qt. Занятие 08.
C++ STL & Qt. Занятие 08.
Igor Shkulipa
 
C++ STL & Qt. Занятие 05.
C++ STL & Qt. Занятие 05.C++ STL & Qt. Занятие 05.
C++ STL & Qt. Занятие 05.
Igor Shkulipa
 
C++ весна 2014 лекция 5
C++ весна 2014 лекция 5C++ весна 2014 лекция 5
C++ весна 2014 лекция 5
Technopark
 
C++ STL & Qt. Занятие 01.
C++ STL & Qt. Занятие 01.C++ STL & Qt. Занятие 01.
C++ STL & Qt. Занятие 01.
Igor Shkulipa
 
C++ STL & Qt. Занятие 06.
C++ STL & Qt. Занятие 06.C++ STL & Qt. Занятие 06.
C++ STL & Qt. Занятие 06.
Igor Shkulipa
 
C++ STL & Qt. Занятие 02.
C++ STL & Qt. Занятие 02.C++ STL & Qt. Занятие 02.
C++ STL & Qt. Занятие 02.
Igor Shkulipa
 
Память в Java. Garbage Collector
Память в Java. Garbage CollectorПамять в Java. Garbage Collector
Память в Java. Garbage Collector
Olexandra Dmytrenko
 
Шишки, набитые за 15 лет использования акторов в C++
Шишки, набитые за 15 лет использования акторов в C++Шишки, набитые за 15 лет использования акторов в C++
Шишки, набитые за 15 лет использования акторов в C++
Yauheni Akhotnikau
 
C++ осень 2013 лекция 4
C++ осень 2013 лекция 4C++ осень 2013 лекция 4
C++ осень 2013 лекция 4
Technopark
 
C++ осень 2013 лекция 9
C++ осень 2013 лекция 9C++ осень 2013 лекция 9
C++ осень 2013 лекция 9
Technopark
 
Современный статический анализ кода: что умеет он, чего не умели линтеры
Современный статический анализ кода: что умеет он, чего не умели линтерыСовременный статический анализ кода: что умеет он, чего не умели линтеры
Современный статический анализ кода: что умеет он, чего не умели линтеры
corehard_by
 
C++ осень 2013 лекция 7
C++ осень 2013 лекция 7C++ осень 2013 лекция 7
C++ осень 2013 лекция 7
Technopark
 
C++ refelection and cats
C++ refelection and catsC++ refelection and cats
C++ refelection and cats
corehard_by
 
Александр Фокин, Рефлексия в C++
Александр Фокин, Рефлексия в C++Александр Фокин, Рефлексия в C++
Александр Фокин, Рефлексия в C++
Sergey Platonov
 
Зачем нужна Scala?
Зачем нужна Scala?Зачем нужна Scala?
Зачем нужна Scala?
Vasil Remeniuk
 
SAST и Application Security: как бороться с уязвимостями в коде
SAST и Application Security: как бороться с уязвимостями в кодеSAST и Application Security: как бороться с уязвимостями в коде
SAST и Application Security: как бороться с уязвимостями в коде
Andrey Karpov
 

Similar to Использование Java Native Interface (JNI) и кросплатформенных C/C++ реализаций в Java/Android (20)

Dz Java Hi Load 0.4
Dz Java Hi Load 0.4Dz Java Hi Load 0.4
Dz Java Hi Load 0.4
HighLoad2009
 
Распределённое нагрузочное тестирование на Java
Распределённое нагрузочное тестирование на JavaРаспределённое нагрузочное тестирование на Java
Распределённое нагрузочное тестирование на Java
aragozin
 
Java 9 - кратко о новом
Java 9 -  кратко о новомJava 9 -  кратко о новом
Java 9 - кратко о новом
Леонид Ставила
 
IT-инфраструктура. FAQ для разработчика
IT-инфраструктура. FAQ для разработчикаIT-инфраструктура. FAQ для разработчика
IT-инфраструктура. FAQ для разработчика
Mikhail Chinkov
 
JavaScript-модули "из прошлого в будущее"
JavaScript-модули "из прошлого в будущее"JavaScript-модули "из прошлого в будущее"
JavaScript-модули "из прошлого в будущее"
oelifantiev
 
Леонид Васильев "Python в инфраструктуре поиска"
Леонид Васильев "Python в инфраструктуре поиска"Леонид Васильев "Python в инфраструктуре поиска"
Леонид Васильев "Python в инфраструктуре поиска"
Yandex
 
Java 9 - Back to the Future
Java 9 - Back to the FutureJava 9 - Back to the Future
Java 9 - Back to the Future
Леонид Ставила
 
От Make к Ansible
От Make к AnsibleОт Make к Ansible
От Make к Ansible
Ivan Grishaev
 
Lift, play, akka, rails part1
Lift, play, akka, rails part1Lift, play, akka, rails part1
Lift, play, akka, rails part1
Eduard Antsupov
 
REPL в Node.js: улучшаем быт разработчик
REPL в Node.js: улучшаем быт разработчикREPL в Node.js: улучшаем быт разработчик
REPL в Node.js: улучшаем быт разработчик
IT61
 
Opensource на .NET
Opensource на .NETOpensource на .NET
Opensource на .NET
lugnsk
 
Лекция 12 (часть 1): Языки программирования семейства PGAS: Cray Chapel
Лекция 12 (часть 1): Языки программирования семейства PGAS: Cray ChapelЛекция 12 (часть 1): Языки программирования семейства PGAS: Cray Chapel
Лекция 12 (часть 1): Языки программирования семейства PGAS: Cray Chapel
Mikhail Kurnosov
 
Frontend: Путешествие в мир модульных загрузчиков
Frontend: Путешествие в мир модульных загрузчиковFrontend: Путешествие в мир модульных загрузчиков
Frontend: Путешествие в мир модульных загрузчиков
CodeFest
 
Разговор про Java 9. Extended version
Разговор про Java 9. Extended versionРазговор про Java 9. Extended version
Разговор про Java 9. Extended version
Ivan Krylov
 
Ввведение в java
Ввведение в javaВвведение в java
Ввведение в java
Unguryan Vitaliy
 
Введение в язык программирования «Java»
Введение в язык программирования «Java»Введение в язык программирования «Java»
Введение в язык программирования «Java»
Unguryan Vitaliy
 
Node.js введение в технологию, КПИ #ITmeetingKPI
Node.js введение в технологию, КПИ  #ITmeetingKPINode.js введение в технологию, КПИ  #ITmeetingKPI
Node.js введение в технологию, КПИ #ITmeetingKPI
Timur Shemsedinov
 
Компьютерная графика. Введение в Processing
Компьютерная графика. Введение в ProcessingКомпьютерная графика. Введение в Processing
Компьютерная графика. Введение в Processing
Tatiana Volkova
 
Dz Java Hi Load 0.4
Dz Java Hi Load 0.4Dz Java Hi Load 0.4
Dz Java Hi Load 0.4
HighLoad2009
 
Распределённое нагрузочное тестирование на Java
Распределённое нагрузочное тестирование на JavaРаспределённое нагрузочное тестирование на Java
Распределённое нагрузочное тестирование на Java
aragozin
 
IT-инфраструктура. FAQ для разработчика
IT-инфраструктура. FAQ для разработчикаIT-инфраструктура. FAQ для разработчика
IT-инфраструктура. FAQ для разработчика
Mikhail Chinkov
 
JavaScript-модули "из прошлого в будущее"
JavaScript-модули "из прошлого в будущее"JavaScript-модули "из прошлого в будущее"
JavaScript-модули "из прошлого в будущее"
oelifantiev
 
Леонид Васильев "Python в инфраструктуре поиска"
Леонид Васильев "Python в инфраструктуре поиска"Леонид Васильев "Python в инфраструктуре поиска"
Леонид Васильев "Python в инфраструктуре поиска"
Yandex
 
От Make к Ansible
От Make к AnsibleОт Make к Ansible
От Make к Ansible
Ivan Grishaev
 
Lift, play, akka, rails part1
Lift, play, akka, rails part1Lift, play, akka, rails part1
Lift, play, akka, rails part1
Eduard Antsupov
 
REPL в Node.js: улучшаем быт разработчик
REPL в Node.js: улучшаем быт разработчикREPL в Node.js: улучшаем быт разработчик
REPL в Node.js: улучшаем быт разработчик
IT61
 
Opensource на .NET
Opensource на .NETOpensource на .NET
Opensource на .NET
lugnsk
 
Лекция 12 (часть 1): Языки программирования семейства PGAS: Cray Chapel
Лекция 12 (часть 1): Языки программирования семейства PGAS: Cray ChapelЛекция 12 (часть 1): Языки программирования семейства PGAS: Cray Chapel
Лекция 12 (часть 1): Языки программирования семейства PGAS: Cray Chapel
Mikhail Kurnosov
 
Frontend: Путешествие в мир модульных загрузчиков
Frontend: Путешествие в мир модульных загрузчиковFrontend: Путешествие в мир модульных загрузчиков
Frontend: Путешествие в мир модульных загрузчиков
CodeFest
 
Разговор про Java 9. Extended version
Разговор про Java 9. Extended versionРазговор про Java 9. Extended version
Разговор про Java 9. Extended version
Ivan Krylov
 
Ввведение в java
Ввведение в javaВвведение в java
Ввведение в java
Unguryan Vitaliy
 
Введение в язык программирования «Java»
Введение в язык программирования «Java»Введение в язык программирования «Java»
Введение в язык программирования «Java»
Unguryan Vitaliy
 
Node.js введение в технологию, КПИ #ITmeetingKPI
Node.js введение в технологию, КПИ  #ITmeetingKPINode.js введение в технологию, КПИ  #ITmeetingKPI
Node.js введение в технологию, КПИ #ITmeetingKPI
Timur Shemsedinov
 
Компьютерная графика. Введение в Processing
Компьютерная графика. Введение в ProcessingКомпьютерная графика. Введение в Processing
Компьютерная графика. Введение в Processing
Tatiana Volkova
 
Ad

More from Stfalcon Meetups (20)

Conversion centered design 3
Conversion centered design 3Conversion centered design 3
Conversion centered design 3
Stfalcon Meetups
 
Discovery phase
Discovery phaseDiscovery phase
Discovery phase
Stfalcon Meetups
 
Stfalcon QA Meetup 31.01.2020
Stfalcon QA Meetup 31.01.2020Stfalcon QA Meetup 31.01.2020
Stfalcon QA Meetup 31.01.2020
Stfalcon Meetups
 
Stfalcon QA Meetup 31.01.2020
Stfalcon QA Meetup 31.01.2020Stfalcon QA Meetup 31.01.2020
Stfalcon QA Meetup 31.01.2020
Stfalcon Meetups
 
Stfalcon PM Meetup 21.11
Stfalcon PM Meetup 21.11Stfalcon PM Meetup 21.11
Stfalcon PM Meetup 21.11
Stfalcon Meetups
 
Stfalcon PM Meetup 21.11
Stfalcon PM Meetup 21.11Stfalcon PM Meetup 21.11
Stfalcon PM Meetup 21.11
Stfalcon Meetups
 
Design of the_future_30_05_2019
Design of the_future_30_05_2019Design of the_future_30_05_2019
Design of the_future_30_05_2019
Stfalcon Meetups
 
2 5404811386729530203
2 54048113867295302032 5404811386729530203
2 5404811386729530203
Stfalcon Meetups
 
Team evolution
Team evolutionTeam evolution
Team evolution
Stfalcon Meetups
 
Mobile&Privacy
Mobile&PrivacyMobile&Privacy
Mobile&Privacy
Stfalcon Meetups
 
Global sales - a few insights
Global sales - a few insightsGlobal sales - a few insights
Global sales - a few insights
Stfalcon Meetups
 
How to build your own startup
How to build your own startupHow to build your own startup
How to build your own startup
Stfalcon Meetups
 
Первая и последняя встреча с клиентом
Первая и последняя встреча с клиентом Первая и последняя встреча с клиентом
Первая и последняя встреча с клиентом
Stfalcon Meetups
 
Парнерство нидерланды
Парнерство нидерландыПарнерство нидерланды
Парнерство нидерланды
Stfalcon Meetups
 
Риси гарного менеджера
Риси гарного менеджераРиси гарного менеджера
Риси гарного менеджера
Stfalcon Meetups
 
Между заказчиком и разработчиком
Между заказчиком и разработчикомМежду заказчиком и разработчиком
Между заказчиком и разработчиком
Stfalcon Meetups
 
Cv vs resume
Cv vs resumeCv vs resume
Cv vs resume
Stfalcon Meetups
 
Vue.js
Vue.jsVue.js
Vue.js
Stfalcon Meetups
 
майстер-клас “Управління ризиками”
майстер-клас “Управління ризиками”майстер-клас “Управління ризиками”
майстер-клас “Управління ризиками”
Stfalcon Meetups
 
Kubernetes: від знайомства до використання у CI/CD
Kubernetes: від знайомства до використання у CI/CDKubernetes: від знайомства до використання у CI/CD
Kubernetes: від знайомства до використання у CI/CD
Stfalcon Meetups
 
Conversion centered design 3
Conversion centered design 3Conversion centered design 3
Conversion centered design 3
Stfalcon Meetups
 
Stfalcon QA Meetup 31.01.2020
Stfalcon QA Meetup 31.01.2020Stfalcon QA Meetup 31.01.2020
Stfalcon QA Meetup 31.01.2020
Stfalcon Meetups
 
Stfalcon QA Meetup 31.01.2020
Stfalcon QA Meetup 31.01.2020Stfalcon QA Meetup 31.01.2020
Stfalcon QA Meetup 31.01.2020
Stfalcon Meetups
 
Design of the_future_30_05_2019
Design of the_future_30_05_2019Design of the_future_30_05_2019
Design of the_future_30_05_2019
Stfalcon Meetups
 
Global sales - a few insights
Global sales - a few insightsGlobal sales - a few insights
Global sales - a few insights
Stfalcon Meetups
 
How to build your own startup
How to build your own startupHow to build your own startup
How to build your own startup
Stfalcon Meetups
 
Первая и последняя встреча с клиентом
Первая и последняя встреча с клиентом Первая и последняя встреча с клиентом
Первая и последняя встреча с клиентом
Stfalcon Meetups
 
Парнерство нидерланды
Парнерство нидерландыПарнерство нидерланды
Парнерство нидерланды
Stfalcon Meetups
 
Риси гарного менеджера
Риси гарного менеджераРиси гарного менеджера
Риси гарного менеджера
Stfalcon Meetups
 
Между заказчиком и разработчиком
Между заказчиком и разработчикомМежду заказчиком и разработчиком
Между заказчиком и разработчиком
Stfalcon Meetups
 
майстер-клас “Управління ризиками”
майстер-клас “Управління ризиками”майстер-клас “Управління ризиками”
майстер-клас “Управління ризиками”
Stfalcon Meetups
 
Kubernetes: від знайомства до використання у CI/CD
Kubernetes: від знайомства до використання у CI/CDKubernetes: від знайомства до використання у CI/CD
Kubernetes: від знайомства до використання у CI/CD
Stfalcon Meetups
 
Ad

Использование Java Native Interface (JNI) и кросплатформенных C/C++ реализаций в Java/Android

  • 1. Android NDK & JNI Использование Java Native Interface (JNI) и кросплатформенных C/C++ реализаций в Java (Android) Sergey Komlach GDG Kremenchuk, StickyPassword Skype: s.komlach sergey.komlach@stickypassword.com
  • 2. ● Что такое JNI/NDK? Быстродействие, много готовых либ, платформозависимость, не- "Write once, run anywhere" (WORA), аналогия с Reflection, используемые типы и вызовы ● Настройка окружения (NDK x 2), отладка, поддержка и тестирование всех платформ ● Пример простейшей реализации Java → C. ● Вызов из С++ метода Java как колбека (Java interface) ● Особенности выполнения кода (BlackBerry10 (mktime()), IntelAtom, х64), tmpdir(), флаги оптимизации, порезаный Bionic и прочие либы в Андроид, удаление SO-шек на Sony при апдейте Рассмотрим….
  • 3. Wiki: Java Native Interface (JNI) — стандартный механизм для запуска кода, под управлением виртуальной машины Java (JVM), который написан на языках С/С++ или Ассемблера, и скомпонован в виде динамических библиотек, позволяет не использовать статическое связывание. Это даёт возможность вызова функции С/С++ из программы на Java, и наоборот. Более ранние интерфейсы, в отличие от JNI, не удовлетворяли условию двоичной совместимости. Wiki: В 2009 году в дополнение к ADT был опубликован Android Native Development Kit (NDK) — пакет инструментариев и библиотек, позволяющий реализовать часть приложения на языке С/С++. NDK рекомендуется использовать для разработки участков кода, критичных к скорости. Реально же наиболее частое применение: Работа с OpenGL ES Использование кросс-платформенных игровых движков, например Cocos2Dx Использование уже написанного на C/C++ кода (а его ох как дофига написано!). Часто, это работа с мультимедиа, например FFMPEG, libpng или наукоемкие вещи типа openCV «Обход» «бутылочного горлышка» в программе (UP! «тяжелых» процессов) Кроссплатформенное (повторное) использование кода JNI/NDK
  • 4. Работа с NDK на порядок усложняет разработку. - Разработчик должен понимать Java (само собой) - С/С++ (особенно внимание на память, указатели, треды/семафоры и т.д) - команды и принципы работы JVM (очень пригодится если вы уже работали с Reflection) Class cls = sample1.getClass(); try { cls.getDeclaredMethod("print", String.class).invoke(sample1, "sample class"); cls.getDeclaredMethod("print", String.class).invoke(sample1, "test string"); cls.getDeclaredMethod("print", null).invoke(sample2, null); cls.getDeclaredMethod("print", null).invoke(sample3, null); } catch (Exception e) {} - Нужно учитывать большое количество ограничений JNI в Android (порезаные библиотека, размеры типов, «пустышки» реализаций) - Сложная настройка среды и особенно отладка Таким образом, работа с NDK чаще всего представляем из себя процесс (часто — мучительный) сборки некой библиотеки и написиние оберток (wrappers) на нативные методы. В тоже время, сейчас есть возможность ваять приложение практически без использования Java, используя NativeActivity (API 9 и выше).
  • 5. package com.example; public class NativeTest{ static { System.loadLibrary("nativetest"); // libs/armeabi-v7a/libnativetest.so } public native boolean testMethod(int arg); } JNIEXPORT jboolean JNICALL Java_com_example_NativeTest_testMethod (JNIEnv *env, jobject caller, jint arg); JNIEXPORT — необходимый для JNI модификатор. Типы данных с префиксом «j»: jdouble, jobject, jstring etc — это «отражения» объектов и типов Java в C/C++. Именование
  • 6. jstring JAVA_JNI_This_1Is_1Native_00024Wrapper_00024_000408_000413_000397(...) Дело в том, что _1 это аналог нижнего подчёркивания. _00024 это символ $, то есть может как разделитель внутреннего класса использоваться. _00408, 0xxxx, это код в юникоде. В итоге получается: class JNI { static class This_Is_Native { static class Wrapper$ { static String Юникод(...) } Именование, часть 2
  • 7. Java JNI JNI array Code Array Code boolean jboolean jbooleanArray Z [Z byte jbyte jbyteArray B [B char jchar jcharArray C [C double jdouble jdoubleArray D [D float jfloat jfloatArray F [F int jint jintArray I [I long jlong jlongArray J [J short jshort jshortArray S [S Object/Class/ String jobject/jclass/ jstring jobjectArray/-/- L/L/L [L/[L/[L void void - V -
  • 9. ● Устаналивается APK ● Если внутри находятся SO-файлы (аналог DLL) они копируются в /data/data/apppackage/app_lib/*.so ● При первом обращении к классу, использующему нативные библиотеки, последние загружаются через System.load(«name») ● Библиотека «живет» пока не будет завершено приложение Как работает взаимодействие между Java и Native
  • 10. ● Качаем NDK. При чем если хотим все платформы, то нужно NDK x32 (для arm6, arm7a, x86 & mips) и NDK x64 (arm8, x86_64 & mips_64 и все х32) ● Устанавливаем окружение (путь к папке NDK) ● «цепляем» в IDE С чего начинается NDK
  • 11. javah создает файлы заголовков и исходники C из Java класса. Эти файлы обеспечивают связь, которая позволит взаимодействовать вашему Java и C коду javah -classpath bin/classes -jni -d jni com.my.javaclass javah
  • 12. Application.mk APP_PLATFORM := android-9 APP_STL := stlport_static APP_ABI := all32 APP_CPPFLAGS += -std=c++11 Android.mk LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_CPP_FEATURES += rtti # Enable exceptions in Android.mk LOCAL_CPP_FEATURES += exceptions # Enable exceptions in Android.mk LOCAL_LDLIBS := -llog -lz LOCAL_MODULE := nativeTest LOCAL_CFLAGS := -DANDROID -O3 -pipe LOCAL_CXXFLAGS := -DANDROID -O3 -pipe LOCAL_SRC_FILES :=com_test.cpp Android.mk & Application.mk
  • 14. - Логгирование __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__) - StackTrace в LogCat Dalvik: F/libc (17861): invalid address or address of corrupt block 0x7f51ce50 passed to dlfree F/libc (17861): Fatal signal 11 (SIGSEGV) at 0xdeadbaad (code=1), thread 29266 (Thread-9488) ART: A/art(21149): sart/runtime/check_jni.cc:65] JNI DETECTED ERROR IN APPLICATION: input is not valid Modified UTF-8: illegal start byte 0xa3 …. A/art(21149): sart/runtime/check_jni.cc:65] native: #07 pc 000bfaad /system/lib/libart.so (art::CheckJNI::NewStringUTF (_JNIEnv*, char const*)+44) A/art(21149): sart/runtime/check_jni.cc:65] native: #08 pc 00008fbb /data/app/com.stickypassword.android- 1/lib/arm/libSPCAgent.so (setValue(_jobject*, int, long, char*, char*)+202) A/art(21149): sart/runtime/check_jni.cc:65] native: #09 pc 00009ac7 /data/app/com.stickypassword.android- 1/lib/arm/libSPCAgent.so (Java_com_spc_SPCManager_GetAuthCredentialsV2+82) Отладка
  • 15. GDB (GNU Debugger) — переносимый отладчик проекта GNU, который работает на многих UNIX- подобных системах и умеет производить отладку многих языков программирования, включая Си, C++, Free Pascal, FreeBASIC, Ada и Фортран. GDB — свободное программное обеспечение, распространяемое по лицензии GPL. GDB
  • 16. package com.example.testsimplycall; public class NativeTest { static { try{ // == Runtime.getRuntime().loadLibrary("testSimplyCall"); System.loadLibrary("testSimplyCall"); } catch (UnsatisfiedLinkError err){ //need catch exception err.printStackTrace(); } } public native void testMePlz(String msg); }
  • 17. project/jni/com_example_testsimplycall_NativeTest.h /* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> #ifndef _Included_com_example_testsimplycall_NativeTest #define _Included_com_example_testsimplycall_NativeTest #ifdef __cplusplus extern "C" { #endif JNIEXPORT void JNICALL Java_com_example_testsimplycall_NativeTest_testMePlz(JNIEnv *env,jobject jobj, jstring msg); #ifdef __cplusplus } #endif #endif project/jni/com_example_testsimplycall_NativeTest.cpp #include <def.h> #include <jni.h> #include "com_example_testsimplycall_NativeTest.h" JNIEXPORT void JNICALL Java_com_example_testsimplycall_NativeTest_testMePlz(JNIEnv *env, jobject jobj, jstring msg){ jboolean isCopy; const char * Str; Str = env->GetStringUTFChars(msg, &isCopy); LOGI("string = "%s"",Str); }
  • 18. package com.example.testcallback; import android.util.Log; public interface NativeCallback { public void print(String str); } public class NativeTest { static { try{ System.loadLibrary("testCallback"); } catch (UnsatisfiedLinkError err){ err.printStackTrace(); } } public NativeCallback nativecallback = new NativeCallback(){ @Override public void print(String str) { Log.d("JAVA_CALLBACK", str); }}; public native void testMePlz(String msg); public native void SetListener(NativeCallback javacallback); }
  • 19. /* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> #ifndef _Included_com_example_testcallback_NativeTest #define _Included_com_example_testcallback_NativeTest #ifdef __cplusplus extern "C" { #endif JNIEXPORT void JNICALL Java_com_example_testcallback_NativeTest_testMePlz(JNIEnv *env, jobject jobj, jstring msg); JNIEXPORT void JNICALL Java_com_example_testcallback_NativeTest_SetListener( JNIEnv *env, jobject jobj, jobject callback); #ifdef __cplusplus } #endif #endif
  • 20. #include <jni.h> #include <string.h> #include <stdio.h> #include <stdlib.h> #include "com_example_testcallback_NativeTest.h" jobject javaCallback; JavaVM* mJVM; /* Reference to Java-object*/ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) { mJVM = jvm; return JNI_VERSION_1_2; } JNIEnv* getJniEnv() { JavaVMAttachArgs attachArgs; attachArgs.version = JNI_VERSION_1_2; attachArgs.name = ">>>NativeThread__Any"; attachArgs.group = NULL; JNIEnv* env; if (mJVM->AttachCurrentThread(&env, &attachArgs) != JNI_OK) { env = NULL; } return env; }
  • 21. void printToLogcat(const char* msg) { JNIEnv* pEnv = getJniEnv(); jclass javaClass = pEnv->GetObjectClass(javaCallback); if (javaClass != NULL) { jmethodID javaMethodID = pEnv->GetMethodID(javaClass, "print","(Ljava/lang/String;)V"); jstring logmsg = pEnv->NewStringUTF(msg); if (logmsg != NULL) { pEnv->CallVoidMethod(javaCallback, javaMethodID, logmsg); pEnv->DeleteLocalRef(logmsg); logmsg = NULL; } pEnv->DeleteLocalRef(javaClass); javaClass = NULL; } } JNIEXPORT void JNICALL Java_com_example_testcallback_NativeTest_SetListener( JNIEnv *env, jobject jobj, jobject callback) { if(javaCallback) env->DeleteGlobalRef(javaCallback); javaCallback = env->NewGlobalRef(callback); } JNIEXPORT void JNICALL Java_com_example_testcallback_NativeTest_testMePlz(JNIEnv *env,jobject jobj, jstring msg){ jboolean isCopy; const char * Str; Str = env->GetStringUTFChars(msg, &isCopy); printToLogcat(Str); }
  • 22. ● Blackberry10 (mktime) ● ARM & Intel ● NDK X32 & х64 ● Android L & 5.0 (копирование массивов) ● tmpdir()/tmpfile() ● флаги оптимизации ( -03,-Ofast, -SSE etc) ● порезаный Bionic и прочие либы в Андроид ● *.so на Sony ● Проблема 01.01.2037 Грабли
  • 23. Android NDK & JNI Использование Java Native Interface (JNI) и кросплатформенных C/C++ реализаций в Java (Android) Q/A Sergey Komlach GDG Kremenchuk, StickyPassword Skype: s.komlach sergey.komlach@stickypassword.com
  翻译: