JNI与NDK的关系

JNI、Binder、NDK 的关系解析(类比 + 场景化说明) 需求:游戏逻辑(C++,NDK)与渲染(另一个 C++ 进程,NDK)高速通信。方案用 NDK 实现 Native Binder 服务(类似 Java 的 AIDL,但全 C++)。通过 JNI 在 Java 层暴露简化接口(可选)。Binder 驱动负责跨进程数据传输(一次内存拷贝,高性能)。四、对比与总结维度JNIBinderNDK作用跨语言(Java ↔ C/C++)跨进程(IPC)支持 Native 开发(C/C++)层级语言边界进程边界开发工具链协作场景。 阅读详情

JNI与NDK的关系

https://www.jianshu.com/p/0d45d59352e5

https://www.jianshu.com/p/b4431ac22ec2

https://www.cnblogs.com/hejunlin/p/12747263.html

https://blog.youkuaiyun.com/shaohuazuo/article/details/43309625

https://www.jianshu.com/p/5f5d7f132c53

  1. JNIEnv概念 :
    JNIEnv是一个线程相关的结构体, 该结构体代表了 Java 在本线程的运行环境。通过JNIEnv可以调用到一系列JNI系统函数。

  2. JNIEnv线程相关性:
    每个线程中都有一个 JNIEnv 指针。JNIEnv只在其所在线程有效, 它不能在线程之间进行传递。

注意:在C++创建的子线程中获取JNIEnv,要通过调用JavaVM的AttachCurrentThread函数获得。在子线程退出时,要调用JavaVM的DetachCurrentThread函数来释放对应的资源,否则会出错。

 将参数类型的域描述符按照申明顺序放入一对括号中后跟返回值类型的域描述符,规则如下: (参数的域描述符的叠加)返回

  类型描述符。对于,没有返回值的,用V(表示void型)表示。举例如下:

                 Java层方法                                               JNI函数签名

                String test ( )                                              Ljava/lang/String;

                int f (int i, Object object)                            (ILjava/lang/Object;)I

                void set (byte[ ] bytes)                                ([B)V

NDK可以为我们生成了C/C++的动态链接库,JNI是java和C/C++沟通的接口,两者与android没有半毛钱关系,只因为安卓是java程序语言开发,然后通过JNI又能与C/C++沟通,所以我们可以使用NDK+JNI来实现“Java+C”的开发方式。

JNIEnv与JavaVM

JNIEnv 概念 : 是一个线程相关的结构体, 该结构体代表了 Java 在本线程的运行环境 ;

JNIEnv 与 JavaVM : 注意区分这两个概念;
– JavaVM : JavaVM 是 Java虚拟机在 JNI 层的代表, JNI 全局只有一个;
– JNIEnv : JavaVM 在线程中的代表, 每个线程都有一个, JNI 中可能有很多个 JNIEnv;

JNIEnv 作用 :
– 调用 Java 函数 : JNIEnv 代表 Java 运行环境, 可以使用 JNIEnv 调用 Java 中的代码;
– 操作 Java 对象 : Java 对象传入 JNI 层就是 Jobject 对象, 需要使用 JNIEnv 来操作这个 Java 对象;

JNIEnv 体系结构
线程相关 : JNIEnv 是线程相关的, 即 在 每个线程中 都有一个 JNIEnv 指针, 每个JNIEnv 都是线程专有的, 其它线程不能使用本线程中的 JNIEnv, 线程 A 不能调用 线程 B 的 JNIEnv;

*.so的入口函数

JNI_OnLoad()与JNI_OnUnload()
当Android的VM(Virtual Machine)执行到System.loadLibrary()函数时,首先会去执行C组件里的JNI_OnLoad()函数。它的用途有二:
(1)告诉VM此C组件使用那一个JNI版本。如果你的.so档没有提供JNI_OnLoad()函数,VM会默认该.so档是使用最老的JNI 1.1版本。由于新版的JNI做了许多扩充,如果需要使用JNI的新版功能,例如JNI 1.4的java.nio.ByteBuffer,就必须藉由JNI_OnLoad()函数来告知VM。
(2)由于VM执行到System.loadLibrary()函数时,就会立即先呼叫JNI_OnLoad(),所以C组件的开发者可以藉由JNI_OnLoad()来进行C组件内的初期值之设定(Initialization) 。

这里写图片描述

这里写图片描述

这里写图片描述

JNI字符串函数

常用的JNI函数将在后续介绍,这里给出其中的字符串操作函数的函数名以及相关描述。

GetStringChars
ReleaseStringChars 获得/释放一个Unicode格式的字符串指针,可能返回一个字符串的副本

GetStringUTFChars
ReleaseStringUTFChars 获得/释放一个UTF-8格式的字符串指针,可能返回一个字符串的副本

GetStringLength 返回Unicode格式字符串的长度

GetStringUTFLength 返回UTF-8格式字符串的长度

NewString 根据Unicode格式的C字符串创建一个Java字符串

NewStringUTF 根据UTF-8格式的C字符串创建一个Java字符串

GetStringCritical
ReleaseStringCritical 获得/释放一个Unicode格式的字符串指针,可能返回一个字符串的副本【在该函数对区间内,不能使用任何JNI函数】

GetStringRegion 将Unicode格式的String复制到预分配的缓冲区中

GetStringUTFRegion 将UTF-8格式的String复制到预分配的缓冲区中

int sprintf( char *buffer, const char *format, [ argument] … );
类似于printf,根据格式化字符串format,将后续参数列表中的参数逐个输出。不过输出目标不是标准输出终端,而是字符串buffer。

字符串操作

C字符串——>java字符串

例如:下面的函数以一个C字符串为参数,并返回一个Java字符串引用类型jstring值。

 

jstring javastring
javastring = (*env)->NewStringUTF(env, "I LOVE YOU !");

注意,在内存溢出的情况下,NewString函数将返回NULL以通知原生代码虚拟机中有异常抛出。

java字符串转换成C字符串

为了在原生代码中使用java字符串,需要先将java字符串转换成C字符串,我们使用GetStringChars函数可以将Unicode格式的java字符串转换成C字符串,使用GetStringUTFChars函数可以将UTF-8格式的Java字符串转换成C字符串。这些函数的第三个参数均为可选参数,该可选参数名是isCopy,它让调用者确定返回的C字符串地址指向副本还是指向堆中的固定对象。例如:

 

const jbyte* str;
jboolean isCopy;

str = (*env)->GetStringUTFChars(env, javaString,&isCopy);
if(0 != str){
    printf("java String: %s",str);
    if(JNI_TRUE == isCopy){
        printf("C String is a copy of the java String");
    }else{
        printf("C String points to actual String");
    }
}

释放字符串
通过JNI GetStringChars 函数GetStringUTFChars函数获得的C字符串在原生代码中使用完成之后需要正确的释放,否则将会引起内存泄漏。通常我们使用ReleaseStringChars函数释放Unicode格式的字符串,使用ReleaseUTFStringChars函数释放UTF-8格式的字符串.

 

(*env)->ReleaseUTFStringChars(env,javaString,str);

数组操作

JNI把java数组当成引用类型来处理,JNI提供必要的函数访问和处理Java数组。

创建数组

 

用NewArray函数在原生代码中创建数组实例,其中可以是Int、Char和Boolean等。例如:

 

jintArray javaArray;
javaArray = (*env)->NewIntArray(env,10);
if(0 != javaArray){
/*数组使用……*/
}

 

注意,在内存溢出的情况下,NewArray函数将返回NULL以通知原生代码虚拟机中有异常抛出。 

访问数组元素

JNI提供两种访问java数组元素的方法,可以将数组的代码赋值成C数组或者让JNI提供直接执行数组元素的指针。

对副本的操作

1.java数组转C数组
GetArrayRegion函数将给定的基本Java数组赋值到给对你给的C数组中,例如:

 


jint nativeArray[10];
(*evn)->GetIntArrayRegion(env,javaArray,0,10,nativeArray);

2.C数组转java数组
原生代码可以像使用普通的C数组一样使用和修改数组元素。当原生代码想将所做的修改提交给java数组时,可以使用SetArrayRegion函数将C数组复制回java数组中。例如:

 

(*env)->SetIntArrayRegion(env,javaArray,0,10,nativeArray);

注意:当数组很大时,对数组做复制操作会引起性能问题。

对直接指针的操作

3.java数组转C数组
原生代码可以使用GetArrayElements函数获取执行数组元素的直接指针。例如:

 

jint nativeDirectArray;
jboolean isCopy;

nativeDirectArray = (*env)->GetIntArrayElements(env,javaArray,&isCopy);

 

其中,第三个&isCopy参数为可选参数,让调用者确定返回的C字符串地址指向副本还是指向堆中的固定对象。 
因为可以像普通的C数组一样访问和处理数组元素,因此JNI没提供访问和处理数组元素的方法,JNI要求原生代码用完这些指针后立刻释放,否则会出现内存溢出。可以使用JNI提供的ReleaseArrayElements函数释放GetArrayElements返回的C数组。例如:

 


(*env)->ReleaseIntArrayRegion(env,javaArray,nativeDirectArray,0);

 

其中第四个参数是释放模式。 
释放模式动作0将内容复制回来并释放原生数组JNI_COMMIT将内容复制回来但是不释放原生数组,一般用于周期性的更新一个java数组JNI_ABORT释放原生数组但不用将内容复制回来

NIO操作

JNI提供了在原生代码中使用NIO(I/O)的函数,与数组操作相比更适合原生代码和java应用程序之间传送大量数据。

创建直接字节缓冲区

原生代码可以创建java应用程序使用的直接字节缓冲区,该过程是以提供一个原生C字节数组为基础,例如:

 

unsigned char* buffer = (unsigned  char*) malloc(1024)
……
jobject directBuffer;
directBuffer = (*env)->NewDirectByteBuffer(env,buffer,1024);

直接字节缓冲区获取

java应用程序中也可以创建直接字节缓冲区,在原生代码中调用GetDirectBufferAddress函数可以获取原生自己数组的内存地址。例如:

 


unsigned char* buffer
buffer = (unsigned char*) (*env)->GetDirectBufferAddress(env,directBuffer);

JNI访问java对象属性

 

// 实例域
private String instanceField = "Instance Field ";
// 静态域
private static String staticField = "Static Field ";

获取域ID
JNI提供了用域ID访问两类域的方法,可以通过给定实例的class对象获取域ID,用GetObjectClass函数可以获得class对象,例如:

 


jclass clazz
clazz = (*env)->GetObjectClass(env,instance);

1.使用GetFieldID获取实例域的ID

 

jfieldID instanceFieldId;
instanceField = (*env)->GetFieldID(env,clazz,"instanceFieldId","Ljava/lang/String;");

2.使用GetStaticFieldID获取静态域的ID

 

jfieldID staticFieldId;
staticFieldId = (*env)->GetStaticFieldID(env,clazz,"staticFieldId","Ljava/lang/String;");

获取域
在获得域ID之后,可以用GetField函数获得实际的实例域,例如:

1.获得实例域

 

jstring instanceFieldId;
instanceField = (*env)->GetObjectField(env,clazz,"instanceFieldId");

2.获得静态域

 


jfieldID staticField;
staticFieldId = (*env)->GetStaticObjectField(env,clazz,"staticFieldId");

两个函数的最后一个参数是java中表示域类型的域描述符,其中”Ljava/lang/String;”表明域类型是Sting。

JNI调用Java方法

 

public class WJavaClass{
// 实例方法
private String instanceMethod(){
return "Instance Method";
}
// 静态方法
private static String staticMethod(){
return "StaticMethod";
}
}

获取方法ID
JNI提供了用方法ID访问两类方法的途径,可以用给定实例的class对象获得方法ID。用GetMethodID函数获得实例方法的方法ID,例如:

 

jmethodID instanceMethodId;
instanceMethodId = (*env)->GetMethodID(env,clazz,"instanceMethod","()Ljava/lang/String;");

用GetStaticMethodID函数获得静态域的方法ID,例如:

 


jmethodID staticMethodId;
staticMethodId = (*env)->GetStaticMethodID(env,clazz,"staticMethod","()Ljava/lang/String;");

两个函数的最后一个参数均表示方法描述符,在Java中表示方法签名。

调用方法
可以以方法ID为参数通过CallMethod类函数调用实际的实例方法,例如:
1.调用实例方法

 


jstring instanceMethodResult;
instanceMethodResult = (*env)->CallStringMethod(env,instance,"instanceMethodId");

2.调用静态方法

 

jstring staticMethodResult;
staticMethodResult = (*env)->CallStaticStringMethod(env,clazz,"staticMethodId");

JNI调用Java静态方法案例

 

public class HelloJni extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        callJavaStaticMethod();
    }

    public native String callJavaStaticMethod();

    static {
        System.loadLibrary("hello-jni");
    }

    // 静态方法
    private static String staticMethod() {
        return "StaticMethod Castiel";
    }
}

 

#include <string.h>
#include <jni.h>
#include <android/log.h>

JNIEXPORT void JNICALL
Java_com_example_hellojni_HelloJni_callJavaStaticMethod(JNIEnv *env, jclass type) {

    jclass jniClass = (*env)->FindClass(env, "com/example/hellojni/HelloJni");
    if (NULL == jniClass) {
        __android_log_print(ANDROID_LOG_INFO,"HelloJni","can't find jclass");
        return;
    }
    jmethodID getMId = (*env)->GetStaticMethodID(env, jniClass, "staticMethod",
                                                              "()Ljava/lang/String;");
    if (NULL == getMId) {
        __android_log_print(ANDROID_LOG_INFO,"HelloJni","can't find method getStringFromStatic from JniClass");
        return;
    }
    jstring result = (*env)->CallStaticObjectMethod(env, jniClass, getMId);
    const char *resultChar = (*env)->GetStringUTFChars(env, result, NULL);
    (*env)->DeleteLocalRef(env, jniClass);
    (*env)->DeleteLocalRef(env, result);
    __android_log_print(ANDROID_LOG_INFO,"HelloJni",resultChar);

JNI异常处理

调用throwingMethod方法时,accessMethod原生方法需要显示地做异常处理。JNI提供了ExceptionOccurred函数查询虚拟机中是否有挂起的现象。例如,原生代码中的异常处理:

 

jthrowable ex;
……
(*env)->CallVoidMethod(env,instance,throwingMethodId);
ex = (*env)->ExceptionOccurred(env);
if(0 != ex){
(*env)->ExceptionClear(env);
/*Exception handler*/
}

抛出异常

 

public class WJavaClass{
// 抛出方法
private void throwingMethod() throws NullPointerException{
throw new NullPointerException("Null Pointer");
}
}

 

JNI也允许原生代码抛出异常。因为异常是java类,应该先用FindClass函数找到异常类。用ThrowNew函数可以初始化且抛出新的异常,例如:

 

jclass clazz;
……
clazz = (*env)->FindClass(env,"java/lang/NullPointerException");
if(0 !=clazz){
(*env)->ThrowNew(env,clazz,"Exception message");
}

JNI的局部引用和全局引用和弱全局引用

局部引用
大多数JNI函数返回局部引用。局部引用不能在后续的调用中被缓存及重用,主要是因为它们的使用期限仅限于原生方法,一旦原生函数返回,局部引用即被释放。例如,使用FindClass函数返回一个局部引用,当原生方法返回时,它被自动释放,也可以用DeleteLocalRef函数显示释放原生代码:

 


jclass clazz
clazz = (*env)->FindClass(env,"java/lang/String");
……
(*env)->DeleteLocalRef(env,clazz);

根据JNI的规范,虚拟机应该允许原生代码创建最少16个局部引用

全局引用
全局引用在原生方法的后续调用过程中依然有效,除非它们被原生代码显示释放。
1.创建全局引用
可以用NewGlobalRef函数将局部引用初始化为全局引用,例如:

 


jclass localclazz
jclass globalclazz
……
localclazz = (*env)->FindClass(env,"java/lang/String");
globalclazz = (*env)->NewGlobalRef(env,localclazz );
……
 (*env)->DeleteLocalRef(env,localclazz );

2.删除全局引用
当原生代码不再需要一个全局引用时,可以随时用DeleteLocalRef函数释放它。

 

 (*env)->DeleteLocalRef(env,globalclazz );

弱全局引用
弱全局引用和全局引用一样,在原生方法的后续调用过程中依然有效。与全局引用不同,弱全局引用并不阻止潜在的对象被垃圾回收。
1.创建弱全局引用
用NewWeakGlobalRef函数对弱全局引用进行初始化,例如:

 


jclass weakGlobalclazz
weakGlobalclazz = (*env)->NewWeakGlobalRef(env,localclazz);

2.弱全局引用的有效性校验
可以使用IsSameObject函数检验一个弱全局引用是否仍然指向活动的类实例,例如:

 


if(JNI_FALSE == (*env)->IsSameObject(env,weakGlobalClazz,NULL)){
/*对象仍然处于活动状态且可以使用*/
}else{
/*对象被垃圾回收期收回,不能使用*/
}

删除弱全局引用
可以随时使用DeleteWeakGlobalRef函数释放弱全局引用。

 

(*env)->DeleteLocalRef(env,weakGlobalClazz);



作者:private_object
链接:https://www.jianshu.com/p/0d45d59352e5
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

android NDK、JNI技术详解及NDK在Android系统架构中的位置关系 在上一篇文章中,我们介绍了NDK的下载地址。 本篇文章,我们主要阐明两个问题 1、什么是Android NDK,及其在Android系统架构中的位置? 2、什么事Android JNI技术以及使用方法? 一、什么事Android NDk Android NDK(Android Native Development Kit)是一系列的开发工具,允许程序开发人员在Android应用程序中 阅读详情

相关推荐

Android C++高级编程使用NDK [ Pro Android C++ with the NDK ]书源码

Android C++高级编程使用NDK [ Pro Android C++ with the NDK ]书源码

Pro Android C++ with the NDK.pdf

下载地址:网盘下载内容简介······Android is one of the major players in the mobile phone market. Android is a mobile platform that is built on the top of Linux operating system. The nativ...

weixin_30485799的博客 323

Pro Android C++ with the NDK

详细介绍Android的NDK开发 What is the Android platform, and getting up to speed with the Android NDK. Using the Eclipse IDE to streamline developing native applications How to use Java Native Interface (JNI) to connect native code to Java world. Auto-generate JNI code using Simplified Wrapper and Interface Generator (SWIG). Introduction to Bionic API Networking through POSIX sockets Developing multithreaded applications using POSIX Threads, and Java Threads. Debug through Logging, GNU Debugger (GDB), and Eclipse Debugger Analyze memory issues through Valgrind C++ Support and Standard Template Library STL Native Graphics through JNI Graphics and OpenGL ES Native Sound through OpenSL ES Profiling the native code using GProf to identify performance bottlenecks Optimize code using SIMD/NEON

离了JNI,NDK还能活吗? 深入探讨Android开发的双刃剑

在Android开发的世界里,Java和Kotlin是构建应用的主要语言。然而,对于需要高性能计算或者访问设备底层功能的场景,Java和Kotlin就显得力不从心。这时,JNI(Java Native Interface)和NDK(Native Development Kit)就显得尤为重要。本文将深入探讨JNI和NDK的概念、用途以及如何在Android开发中有效利用它们。

Unity打怪升级 955

Zemax操作33--5倍激光扩束器

5倍扩束

lzy750750的博客 2932

BUUCTF--[OGeek2019]babyrop

才学习了基本的ROP流程,到处找题练,不过也没做出来几道题,以这道32位的题作为例题吧。 这道题是BUUCTF上pwn练习题里的[OGeek2019]babyrop。 代码审计 老规矩先checksec一下: 没有canary保护,nx保护开启排除shellcode可能性,FULL RELEO为地址随机化。 观察主函数,先设定了一个闹铃,到时间就会强制退出程序,解除闹铃的方法在上一篇博客中提到过了, 这道题中闹铃函数依然对我们解题起不到什么干扰作用。 主函数的思路大概是:生成一个随机数,把这个随机数作为

N1rvana的博客 6007

NDK 与 JNI 的关系

简介 JNI是java语言提供的Java和C/C++相互沟通的机制,Java可以通过JNI调用本地的C/C++代码,本地的C/C++的代码也可以调用java代码。JNI 是本地编程接口,Java和C/C++互相通过的接口。Java通过C/C++使用本地的代码的一个关键性原因在于C/C++代码的高效性。 NDK是一系列工具的集合。它提供了一系列的工具,帮助开发者快速开发C(或C++)的动态库,...

836811384 299

ollama服务暴露公网?三步搞定Nginx反向代理配置(避坑指南)

本文详细介绍了如何通过Nginx反向代理安全地将Ollama服务暴露到公网,避免直接修改OLLAMA_HOST带来的安全隐患。文章提供了从SSL证书部署到高级安全加固的全流程实战指南,包括IP白名单、基础认证、速率限制等企业级安全措施,帮助用户实现安全可靠的外部访问。

wood5的博客 177

Android NDK学习笔记6-JNI对引用数据类型的操作

字符串操作    JNI把Java字符串当成引用类型来处理,JNI提供了java字符串与C字符串之间相互转换的必要函数。因为java字符串对象是不可变的,因此JNI不提供任何修改现有的java字符串内容的函数。 ● 创建字符串     可以在原生代码中用NewString函数构建Unicode编码格式的字符串实例,用NewStringUTF函数构建UTF-8编码格式的字符串实例。

Android研发专栏 2334

STM32使用ASR01语音播报模块

自己再根据鹿小班模块进行操作进行相关操作,先接上usb数据线。这里提供一套修改好的天问程序模板和stm32f103模板。这里使用的asr01语音播报模块是模块化编程。这里使用的asr01语音播报模块是模块化编程。记得先生成模型再去编译下载。先下载天问block软件。

lml1781978327的博客 1万+

从零构建基于ZYNQ与AD9361的SDR信号源:FPGA逻辑与射频前端的协同设计

本文详细介绍了从零开始构建基于ZYNQ与AD9361的SDR信号源的完整流程。通过解析FPGA逻辑与射频前端的协同设计,重点阐述了如何利用FPGA生成基带信号,并通过ARM处理器配置AD9361,最终实现一个可编程的2.4GHz载波信号发生器。内容涵盖硬件选型、Vivado环境搭建、AXI总线通信、LVDS接口设计及软件驱动开发,为SDR开发者提供了实用的实战指南。

weixin_29200485的博客 214

【NDK】【001】JNI和NDK的关系

JNI,全称Java Native Interface,是Java语言本身提供的一套Java和C++之间互调的机制 NDK,全称Android Native Development Kit,是一套用于在Android中方便开发C++动态库开发的工具集 NDK可以根据Java中的native方法,生成对应的C++头文件,也可以根据C++代码,编译出可供Java调用的so库 通过以上分析我们...

天天向上 Up Up Up (*^▽^*) 498

【Unity】NGUI下载与导入

Unity3D插件NGUI的下载和导入。

Get your hands dirty 3万+

NDK与JNI的关系

        JNI是Java Native Interface(Java本地编码接口),提供一系列API实现Java与C/C++直接互相操作;         Android NDK是一个开发工具集,提供一系列工具快速开发C/C++的动态库,并能自动将so和java应用一起打包到Apk;         NDK提供工具可以方便JNI调用C/C++,而且提供了交叉编译器可以修改.mk文件生成...

牛八少爷的专栏 2706

【ChangeCLIP】Remote sensing change detection with multimodal vision-language representation learning

ChangeCLIP论文及代码使用详解。持续更新变化检测最新论文,欢迎订阅本专栏。

向上生长的程序媛的博客 1337

视觉测量实战:C#上位机+OpenCVSharp 实现工业零件尺寸自动检测(精准像素级,工业级可落地)

本次开发的上位机界面遵循工业现场操作规范简洁、直观、按钮大、文字清晰、参数可视化调节,操作人员为车间工人/质检员,无需复杂操作,所有控件均为WinForms原生控件,拖拽即可完成布局本次实战完成了C#上位机+OpenCVSharp 工业零件尺寸自动检测系统的完整开发,这套方案是工业视觉测量的标准落地方案,适配95%的规则几何零件的尺寸检测场景,从五金件、塑胶件到电子元件,全覆盖无死角。测量效率提升100倍、精度提升10倍、无人工误差、可适配流水线实时检测。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 849

Android NDK开发简介 NDK和SDK以及JNI有什么关系?

最近由于项目的需要,使用到了Android的NDK技术,对项目核心算法跨平台的移植。简答而言,就是使用C对原来的算法进行了改进,并集成到原 来的app项目里。      从前的项目一直没有使用NDK进行开发的机会,因而一直仰慕那些技术大牛们关于NDK以及C/C++开发而写的文章,觉得很深奥,因而一直蠢蠢欲动。      其实NDK的开发并不复杂,就入门而言甚至可以说是easy job,觉得它难

sanyuancap 1599

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

Android JNI和NDK关系

<br />1、什么JNI<br />Java Native Interface (JNI)标准是java平台的一部分,它允许Java代码和其他语言写的代码进行交互。JNI 是本地编程接口,它使得在 Java 虚拟机 (VM) 内部运行的 Java 代码能够与

elfylin的专栏 7396

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

【NDK开发】JNI与NDK关系

JNI ( java native interface)是一种编程框架,它使得java代码能够与C/C++、汇编等其他编程语言所编写的程序或库函数进行交互,即可调用或者被调用。 而NDK(native development kit)是安卓所提供的能够在安卓应用中嵌入C/C++(本地代码)的一系列工具,这些工具类似于安卓开发SDK,也就是说,我们可以通过NDK实现与SDK一样的功能。

Image 526

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

上一篇: JNI学习积累之一 ---- 常用函数大全
下一篇: ARM指令集
TuxedoLinux
博客等级 码龄9年 268粉丝 34原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值