JNI使用技巧点滴
- 格式:doc
- 大小:67.50 KB
- 文档页数:6
Android中JNI编程的那些事儿(1)2011-06-08 09:19 佚名互联网字号: |JNI译为Java本地接口。
它允许Java代码和其他语言编写的代码进行交互。
在android中提供JNI的方式,让Java程序可以调用C语言程序。
android中很多Java类都具有native 接口,这些接口由本地实现,然后注册到系统中。
AD:Android系统不允许一个纯粹使用C/C++的程序出现,它要求必须是通过Java代码嵌入Native C/C++——即通过JNI的方式来使用本地(Native)代码。
因此JNI对Android底层开发人员非常重要。
如何将.so文件打包到.APK让我们先从最简单的情况开始,假如已有一个JNI实现——libxxx.so文件,那么如何在APK中使用它呢?在我最初写类似程序的时候,我会将libxxx.so文件push到/system/lib/目录下,然后在Java代码中执行System.loadLibrary(xxx),这是个可行的做法,但需要取得/system/lib 目录的写权限(模拟器通过adb remount取得该权限)。
但模拟器重启之后libxxx.so文件会消失。
现在我找到了更好的方法,把.so 文件打包到apk中分发给最终用户,不管是模拟器或者真机,都不再需要system分区的写权限。
实现步骤如下:1、在你的项目根目录下建立libs/armeabi目录;2、将libxxx.so文件copy到 libs/armeabi/下;3、此时ADT插件自动编译输出的.apk文件中已经包括.so文件了;4、安装APK文件,即可直接使用JNI中的方法;我想还需要简单说明一下libxxx.so的命名规则,沿袭Linux传统,lib<something>.so是类库文件名称的格式,但在Java的System.loadLibrary(" something ")方法中指定库名称时,不能包括前缀—— lib,以及后缀——.so。
Android中JNI的使用之一:Java原生JNI的使用、javah指令的使用以及图解教材Java Nativie Interface(JNI,中文名称Java本地接口)标准时Java平台的一部分,它允许Java代码和其他语言写得代码进行交互。
JNI是本地编程接口,它使得Java虚拟机(VM)内部运行的Java代码能够用其他编程语言(如C、C++和汇编语言)编写的应用程序和库进行交互操作。
JNI的主要用途是为了对硬件进行访问以及追求高效率或可重用C/C++库。
Android系统中采用了JNI的方式来调用C/C++方法,然而,在Android系统里进一步加强了Java JNI的使用,使JNI的调用更具有效率。
因此,总的来说,Android 系统里可以采用两种方式来使用JNI。
第一种:Java原生JNI,使用dll等动态链接库;第二种,Android加强版JNI,通过动态加载*.so链接库来进行JNI调用。
今天,我们分析第一种JNI使用方式,也称得上是JNI入门。
由于Java与其他编程语言采用的语法不同,为了让Java与C/C++库函数能进行通信,约定的一个参数类型映射如下:Java类型C/C++类型void voidjboolean booleanjint intjlong longjdouble doublejfloat floatjbyte jbytejchar charjshort shor上面的只是简单类型的一个映射,后面我们会完善其他参数类型的映射。
开发环境介绍(Windows下):Eclipse:主要用来创建Java工程MicrosoftVC++6.0:生成动态链接库供相应的Java文件加载一、使用Eclipse创建Java工程本例中,我们简单的创建了一个Java工程HelloBabyJNI,工程绝对路径位于E:\MyCode\AndroidCode\HelloBabyJNI路径下,主文件路径位于\src\lover\hellojni路径下(路径对后面的javah编译很重要)HelloBabyJNI.java文件如下:[java] view plaincopyprint?1.package com.lover.hellojni;2.3./**4. * 一个简单的Java JNI实例5. *6. */7.public class HelloBabyJNI {8.9./*10. * 静态构造函数,动态加载HelloBabyJNI动态库,其dll文件名为:HelloBabyJNI.dll --->由MSVC6.0软件创建11. */12.static {13. System.load("E:/HelloBabyJNI.dll"); // 可能需要 dll链接库的绝对存放路径14. }15.16./*17. * 在Java中注册需要调用的C/C++本地方法(native method),也就是需要C/C++来实现的方法18. */19.public native int add(int a, int b);20.21.// main方法,加载动态库来调用C/C++本地方法22.public static void main(String[] args) {23. HelloBabyJNI helloBabyJNI = new HelloBabyJNI();24.// 调用注册的add方法来得到返回值25.int result = helloBabyJNI.add(2, 3);26.// 输出27. System.out.println("after invoke the native method,the result is "+ result);28. }29.}2,编译HelloBabyJNI.java文件,生成HelloBabyJNI.class文件,位于路径\src\lover\hellojni\HelloBabyJNI.class3,使用javah指令编译HelloBabyJNI.class文件,生成Java与C/C++之间进行通信的约定接口,它规定了Java中nativemethod在C/C++的具体接口。
jni method 三种调用方法详解-回复JNI(Java Native Interface)是Java提供的一种编程接口,用于在Java 程序中调用C/C++编写的本地代码。
在JNI中,有三种主要的调用方法,分别是:1. 静态方法调用2. 实例方法调用3. 字段访问下面将详细介绍每种调用方法的使用步骤和具体操作。
一、静态方法调用静态方法调用是指在Java程序中通过JNI调用C/C++编写的静态方法。
1. 创建Java类和Java本地方法接口(JNI):首先,我们需要创建一个Java类,并在该类中声明一个native方法,用于和本地代码进行交互。
然后,使用`javac`命令编译Java类,生成字节码文件。
接着,使用`javah`命令生成C/C++头文件,该头文件中声明了Java本地方法接口的函数签名。
2. 在C/C++中实现Java本地方法接口:使用C/C++编写实现Java本地方法接口的代码,并编译成动态链接库(DLL/SO)。
确保实现的函数原型和Java本地方法接口中声明的函数原型一致。
3. 加载和调用本地方法:在Java程序中使用System.loadLibrary()或者System.load()加载编译生成的动态链接库。
然后,通过Java类对象的方法调用,调用C/C++编写的静态方法。
二、实例方法调用实例方法调用是指在Java程序中通过JNI调用C/C++编写的实例方法。
1. 创建Java类和Java本地方法接口(JNI):同样的,首先创建一个Java类,并在该类中声明一个native方法,用于和本地代码进行交互。
然后,使用`javac`命令编译Java类,生成字节码文件。
接着,使用`javah`命令生成C/C++头文件,该头文件中声明了Java 本地方法接口的函数签名。
2. 在C/C++中实现Java本地方法接口:使用C/C++编写实现Java本地方法接口的代码,并编译成动态链接库(DLL/SO)。
jni 函数JNI(Java Native Interface)函数是Java语言与本地代码(C/C++)交互的接口协议,可以实现Java应用程序与本地程序之间的互操作。
在使用JNI函数时需要注意一些问题。
首先,调用本地代码需要在Java程序中载入本地库文件。
通过System.loadLibrary函数可以载入本地库文件,也可以通过System.load函数手动载入一个本地库文件。
其次,编写本地代码时需要按照JNI规范编写函数接口。
JNI函数名格式为Java_packagename_Classname_Methodname。
其中,packagename、Classname、Methodname分别为Java程序中类的包名、类名和方法名。
在编写本地代码时,需要使用C/C++编程语言,同时符合JNI规定的函数接口格式,即:JNIEXPORT returnType JNICALLJava_packagename_Classname_Methodname(JNIEnv *env, jobject obj, argtype arg);其中,JNIEXPORT和JNICALL是宏定义,returnType表示函数返回值类型,env是JNIEnv结构的指针,obj是Java对象,argtype是函数参数类型。
最后,需要注意内存管理问题。
Java内存管理由JVM(Java Virtual Machine)自动管理,但在本地代码中需要手动对内存进行管理。
在使用指针时需要注意内存泄漏和空指针异常问题。
总之,JNI函数是Java程序与本地代码交互的桥梁,需要注意本地库文件载入、JNI规范编写函数接口和内存管理等问题。
熟练掌握JNI函数是提高Java程序性能和实现复杂功能的必备技能。
jni跨线程调用注意事项在Android开发中,JNI(Java Native Interface)是实现Java与C/C++之间交互的桥梁。
通过JNI,我们可以在Java代码中调用C/C++的函数,并且在C/C++中也可以调用Java的方法。
而在JNI 中跨线程调用时,需要特别注意一些事项,以确保线程安全和正确性。
1. 线程安全问题:JNI调用涉及到多个线程之间的交互,因此首先要考虑线程安全性。
在JNI中,每个线程都有自己的JNIEnv环境,因此可以使用JNIEnv来保证线程安全。
在JNI函数中,可以使用JNIEnv的函数来获取当前线程的JNIEnv环境,并在使用JNIEnv时进行同步操作,以避免多线程并发操作引发的竞态条件和数据不一致问题。
2. 线程切换开销:JNI跨线程调用涉及到线程的切换,而线程切换会引入一定的开销。
因此,在设计JNI跨线程调用时,要尽量减少线程切换的次数。
可以通过合理的线程划分和任务调度来减少线程切换的开销,提高JNI跨线程调用的效率。
3. 线程同步问题:在JNI跨线程调用过程中,可能存在多个线程同时修改共享数据的情况,因此需要进行线程同步操作,以避免数据竞争和数据一致性问题。
可以使用互斥锁、条件变量等同步机制来保证线程间的同步和互斥访问。
4. 线程优先级问题:在JNI跨线程调用中,不同的线程可能具有不同的优先级。
因此,在设计JNI跨线程调用时,要考虑线程优先级的问题,合理设置不同线程的优先级,以防止线程优先级导致的饥饿和优先级反转等问题。
5. 线程异常处理:在JNI跨线程调用中,可能出现线程异常的情况,如线程死锁、线程崩溃等。
因此,要合理处理线程异常,及时捕获和处理异常,以确保程序的稳定性和可靠性。
6. JNI函数调用的原子性:在JNI中,函数调用是原子性的,即一个JNI函数的调用是不可被中断的。
因此,在设计JNI跨线程调用时,要考虑JNI函数的原子性,避免在JNI函数执行过程中被中断导致的状态不一致和数据异常。
详解AndroidJNI的基本使⽤(CMake)简介什么是JNIJNI的全称是Java Native Interface:Java本地开发接⼝,它提供了若⼲的API实现了Java和其他语⾔的通信(主要是C和C++),⽬的就是Java可以调⽤C或C++开发的函数,C或C++也能调⽤Java的⽅法。
这样有很多有点,其⼀就是效率,C/C++是本地语⾔,⽐java更⾼效;其⼆就是可以复⽤已经存在的C/C++代码;其三是Java反编译⽐C语⾔容易,⼀般加密算法都是⽤C语⾔编写,不容易被反编译。
什么是NDK和CMakeNDK全称是Native Development Kit,NDK提供了⼀系列的⼯具,帮助开发者快速开发C(或C++)的动态库,并能⾃动将so和Java应⽤⼀起打包成apk。
NDK集成了交叉编译器,并提供了相应的mk⽂件隔离CPU、平台、ABI等差异,开发⼈员只需要简单修改mk⽂件(指出“哪些⽂件需要编译”、“编译特性要求”等),就可以创建出so。
CMake是⼀个⽐make更⾼级的编译配置⼯具,它可以根据不同平台、不同的编译器,⽣成相应的Makefile或者vcproj项⽬。
通过编写CMakeLists.txt,可以控制⽣成的Makefile,从⽽控制编译过程。
CMake⾃动⽣成的Makefile不仅可以通过make命令构建项⽬⽣成⽬标⽂件,还⽀持安装(make install)、测试安装的程序是否能正确执⾏(make test,或者ctest)、⽣成当前平台的安装包(make package)、⽣成源码包(make package_source)、产⽣Dashboard显⽰数据并上传等⾼级功能,只要在CMakeLists.txt中简单配置,就可以完成很多复杂的功能,包括写测试⽤例。
如果有嵌套⽬录,⼦⽬录下可以有⾃⼰的CMakeLists.txt。
使⽤流程1、在java⽂件中创建本地⽅法2、build项⽬后⾃动⽣成“.h”⽂件3、创建.cpp⽂件,实现.h⽂件中的⽅法4、配置Cmake⽂件,⽣成“.so”⽂件笔者项⽬⽬录如下:测试实例public class MyJNI {private static final String TAG=MyJNI.class.getName();@Testpublic void test(){JNITest jniTest=new JNITest();Log.d(TAG,jniTest.nativeCalculate(2)+"");}}1、调⽤native⽅法nativeCalculate,传⼊参数2。
java jni方法一、JNI简介JNI(Java Native Interface)是Java虚拟机(JVM)的一个组成部分,它允许Java代码与其他编程语言(如C、C++等)编写的本地代码进行交互。
通过JNI,Java程序可以调用本地代码,实现Java与本地代码的互操作,充分发挥Java平台的可扩展性。
二、JNI的应用场景1.性能优化:当Java代码需要执行一些耗时较长的本地操作时,可以通过JNI调用本地代码,提高程序的执行效率。
2.集成现有系统:在很多情况下,我们需要继承和改造现有的本地系统,通过JNI可以方便地实现这一目标。
3.跨平台开发:JNI允许在不同平台上编写本地代码,实现跨平台应用的开发。
三、JNI编程步骤1.编写Java代码:首先,我们需要编写一个Java类,声明native方法,并在Java代码中调用该方法。
2.编写本地代码:接着,根据Java方法的签名,编写相应的本地代码(如C、C++等)。
3.编译Java代码:将Java代码编译成字节码,并使用javac或javah命令生成JNI头文件。
4.编译本地代码:将本地代码编译成可执行文件。
5.编写Java代码调用本地代码:在Java代码中,使用JNI API调用本地代码。
四、JNI实战案例案例:使用JNI实现文件上传功能1.编写Java代码:创建一个Java类,声明一个native方法,用于实现文件上传功能。
2.编写本地代码:使用C语言编写一个文件上传的本地函数。
3.编译并调用:编译Java代码和本地代码,实现在Java代码中调用本地代码实现文件上传功能。
五、JNI的未来发展趋势随着Java技术的不断发展,JNI在跨平台开发、性能优化等方面的应用将更加广泛。
同时,Java 11等新版本的出现,也为JNI带来了更多便利。
我们可以预见,JNI在未来将继续发挥重要作用,助力Java开发者构建高效、跨平台的应用。
总结:JNI作为Java虚拟机的一个重要组成部分,为Java程序提供了与本地代码互操作的途径。
jni语法JNI是Java Native Interface的缩写,它是一种Java与本地代码交互的技术。
在Java应用程序中,JNI提供了一种机制,使其能够调用本地代码(如C或C++代码),并允许本地代码访问Java中的数据和对象。
在本文中,我们将重点介绍JNI语法,帮助读者更好地理解和掌握这项技术。
1. 定义本地方法首先,我们需要在Java代码中定义一个需要调用本地方法的类。
例如,我们有一个名为MyClass的Java类,我们需要在其中定义一个本地方法:public native void someMethod();注意,在本地方法的方法名后加上native关键字是必要的,以标识这是一个本地方法。
2. 生成本地方法头文件现在,我们需要使用Java本机开发工具(如Java开发包中的javah命令)生成一个本地方法头文件。
使用如下命令生成本地方法头文件:javah -classpath . MyClass然后,我们将得到名为MyClass.h的头文件,在其中我们可以看到以下本地方法的定义:JNIEXPORT void JNICALL Java_MyClass_someMethod(JNIEnv *, jobject);其中,JNIEXPORT和JNICALL是两个宏定义,对应于JNI的标准API方法。
3. 实现本地方法现在,我们需要在本地代码中实现someMethod()方法。
在C或C++代码中,我们可以实现这个方法如下:JNIEXPORT void JNICALL Java_MyClass_someMethod(JNIEnv*env, jobject obj) {printf("Hello World!");}在这个本地方法中,有两个参数:JNIEnv和jobject。
JNIEnv指针允许访问Java的运行时系统,而jobject指向调用方法的Java对象。
4. 将本地代码连接到Java一旦我们实现了本地方法,我们需要将本地代码连接到Java代码,使Java应用程序能够调用本地方法。
jni高级用法JNI(Java Native Interface)是一种允许Java代码与其他编程语言进行交互的机制。
虽然大多数开发者可能只使用JNI来调用C或C++编写的库,但实际上,JNI还有许多高级用法可以发挥。
一种常见的JNI高级用法是动态注册。
通常情况下,我们需要在Java代码中使用`System.loadLibrary()`加载一个动态链接库来调用其中的函数。
然而,借助动态注册,我们可以绕过这个步骤。
动态注册允许我们在运行时直接在Java代码中注册本机方法,而无需显式加载库。
这样可以减少一些开发的繁琐过程,并增加代码的可读性。
另一个高级用法是使用JNI实现双向通信。
通常,在JNI中,我们只能从Java代码调用本地方法,以便在本地进行一些操作。
但是,我们也可以通过JNI让本地代码调用Java代码。
这样,我们可以在本地代码中处理一些复杂的操作,然后将结果传递回Java端,以便在应用程序中使用。
JNI还可以用于实现性能优化。
由于JNI调用的开销相对较高,使用JNI调用频繁的方法可能会导致性能下降。
为了解决这个问题,我们可以使用JNI直接在本地代码中进行一些耗时的计算,然后将结果返回给Java代码。
这样可以减少JNI调用的次数,从而提高整体性能。
除了上述提到的高级用法,JNI还可以用于很多其他场景,比如实现Java与其他编程语言之间的数据交换、实现跨平台的特定功能、调用硬件相关的功能等等。
不过,在使用JNI时,需要注意一些潜在的问题,比如内存管理、线程安全性等。
正确地使用JNI,可以为我们的应用程序带来更多的灵活性和性能优势。
总之,JNI是一种强大的工具,具备许多高级用法。
通过动态注册、双向通信、性能优化等方式,我们可以充分利用JNI的潜力。
然而,在使用时需要注意合理的使用场景,并遵循JNI的最佳实践,以确保程序的稳定性和可靠性。
jni用法
JNI(Java Native Interface)是Java语言提供的一种机制,用于实现Java程序与非Java代码的交互。
其核心思想是通过提供一些API和工具,使得Java程序和C/C++等底层语言编写的函数库可以相互调用和共享数据。
使用JNI可以在Java程序中调用C/C++等底层语言编写的函数库,以加速程序的执行和利用底层语言所具有的强大功能。
同时,也可以让底层的代码更轻松地访问Java程序所封装的对象和数据。
在使用JNI的过程中,需要通过Java的javah工具生成.h头文件,并且在本地代码中包含这个头文件。
然后,需要在本地代码中实现Java对应的native方法,并且通过JNI提供的API将Java对象转为本地代码对象,以供本地代码访问。
需要注意的是,在使用JNI的过程中,由于涉及到本地代码,可能会涉及到一些安全隐患。
因此,需要特别注意代码的安全性和稳定性,以免出现不必要的问题。
总之,JNI是Java与非Java代码交互的关键方式之一,为Java 程序提供了更广泛的应用场景和更高效的执行方式,但在使用过程中需要特别注意安全性和稳定性。
jni newstring用法JNI是Java Native Interface的缩写,是Java提供的一种编程规范和工具,用于在Java程序中调用或被调用C/C++编写的本地代码。
JNI提供了一些函数接口供Java程序和本地代码进行交互,其中之一就包括了NewString函数。
NewString函数是JNI提供的一种创建Java中的String对象的方法,它将本地代码中的字符数组或字符串转换为Java中的String对象。
在本文中,我们将详细讨论使用NewString函数的用法和步骤。
一、引入jni.h头文件和获取Java虚拟机指针在使用NewString函数之前,我们需要引入jni.h头文件,并且获取Java 虚拟机指针。
可以通过Java虚拟机环境结构JNIEnv中的GetJavaVM函数来获取Java虚拟机指针。
获取Java虚拟机指针的代码如下:c#include <jni.h>JavaVM* jvm;JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {jvm = vm;return JNI_VERSION_1_6;}此代码将Java虚拟机指针保存在全局变量jvm中,以便后续使用。
二、获取JNIEnv指针在本地代码中,我们需要通过JNIEnv指针与Java虚拟机进行交互。
可以通过Java虚拟机指针获取当前线程的JNIEnv指针。
获取JNIEnv指针的代码如下:cJNIEnv* env;(*jvm)->AttachCurrentThread(jvm, (void)&env, NULL);此代码将当前线程的JNIEnv指针保存在全局变量env中。
三、将字符数组或字符串转换为Java中的String对象在本地代码中,我们可以通过NewString函数将字符数组或字符串转换为Java中的String对象。
JNI使用入门(唐磊2009-8-20)Java和C相互调用安装sun的jdk后,在/opt/sun-jdk-(edition)/include/路径下会产生jni.h的头文件,该文件为实现java和C相互调用提供了接口函数。
本文的思路是:在java 的main函数中调用.c文件中的Cfun()函数,而Cfun()函数调用了.java文件中的javafun()函数。
先编写HelloWorldApp.java文件,对需要调用的Cfun()函数做本地化声明。
//////////* HelloWorldApp.java *///////////public class HelloWorldApp{public static native void Cfun(Test test);static{System.loadLibrary("HelloWorldApp");}}Cfun()函数将在HelloWorldApp.c中定义,HelloWorldApp.c将被编译生成libHelloWorldApp.so的库文件供java调用。
Cfun()函数有一个参数,该参数是java类的对象,将在java文件中定义。
编写Test.java文件,定义java类及其方法javafun(),内容如下://////////* Test.java *//////////public class Test{public void javafun(int a){System.out.println(".java file,javafun() is called! int="+a+"\n");}}编译HelloWorldApp.java,输入命令javac HelloWorldApp.java,当前路径下将会产生两个.class文件:HelloWorldApp.class 和Test.class。
⼀天掌握AndroidJNI本地编程快速⼊门⼀、JNI(Java Native Interface)1、什么是JNI:JNI(Java Native Interface):java本地开发接⼝JNI是⼀个协议,这个协议⽤来沟通java代码和外部的本地代码(c/c++)外部的c/c++代码也可以调⽤java代码2、为什么使⽤JNI:效率上 C/C++是本地语⾔,⽐java更⾼效代码移植,如果之前⽤C语⾔开发过模块,可以复⽤已经存在的c代码java反编译⽐C语⾔容易,⼀般加密算法都是⽤C语⾔编写,不容易被反编译3、Java基本数据类型与C语⾔基本数据类型的对应3、引⽤类型对应4、堆内存和栈内存的概念栈内存:系统⾃动分配和释放,保存全局、静态、局部变量,在站上分配内存叫静态分配,⼤⼩⼀般是固定的堆内存:程序员⼿动分配(malloc/new)和释放(free/java不⽤⼿动释放,由GC回收),在堆上分配内存叫动态分配,⼀般硬件内存有多⼤堆内存就有多⼤⼆、交叉编译1、交叉编译的概念交叉编译即在⼀个平台,编译出另⼀个平台能够执⾏的⼆进制代码主流平台有: Windows、 Mac os、 Linux主流处理器: x86、 arm、 mips2、交叉编译的原理即在⼀个平台上,模拟其他平台的特性编译的流程:源代码-->编译-->链接-->可执⾏程序3、交叉编译的⼯具链多个⼯具的集合,⼀个⼯具使⽤完后接着调⽤下⼀个⼯具4、常见的交叉编译⼯具NDK(Native Development Kit): 开发JNI必备⼯具,就是模拟其他平台特性类编译代码的⼯具CDT(C/C++ Development Tools): 是Eclipse开发C语⾔的⼀个插件,⾼亮显⽰C语⾔的语法Cygwin: ⼀个Windows平台的Unix模拟器(可以参考之前博客)5、NDK的⽬录结构(可以在Google官⽹下载NDK开发⼯具,需要FQ)docs: 帮助⽂档build/tools:linux的批处理⽂件platforms:编译c代码需要使⽤的头⽂件和类库prebuilt:预编译使⽤的⼆进制可执⾏⽂件sample:jni的使⽤例⼦source:ndk的源码toolchains:⼯具链ndk-build.cmd:编译打包c代码的⼀个指令,需要配置系统环境变量三、JNI的第⼀个例⼦好了,准备知识已经完毕,下⾯开始我们的⼀个JNI例⼦。
JNI使用说明一、什么是JNIJNI是java native interface的缩写,java毕竟是一个虚拟机上运行的语言,在虚拟机上的所有问题java语言本身完全可以搞的定。
但是现在如果我在一个linux版本上修改了内核,加上了我自己写的某些东西,这时候java再怎么厉害也不可能能够调用我写的功能,当然 java语言的开发者也非常的了解这一点,作为java VM的扩展,退出了JNI。
至于JNI的其他的说明,可以百度一下,这里就不多说了。
二、为什么需要使用JNI在上面的说明中,已经表现了JNI的一种用途,实际上我们可以这样理解JNI的使用场景,当下编程语言很多java/C/C++/python/matlab/R/perl,每一种语言都是各有特点,如果说需要大量的计算那么使用C语言就比较靠谱,如果需要数据的处理,使用python 或许是一个不错的选择,如果需要进行数学运算或者需要仿真那么MATLAB绝对是首选,我们一般做系统使用java,这时就可以互补的去操作,如果我们需要使用java访问嵌入式的设备,使用C有时是必选的。
这时候使用动态链接库java直接调用,爽爆了。
我们简单的列出使用JNI的一些常见的使用场景:1.现在有两个系统,分别是由java和C编写的,如果说需要把这两个联合起来使用的话,必须使用JNI,否则就要重写系统。
2.一些复杂的算法,大量计算,加解密,编码解码等需要其他语言协助。
3.一些嵌入式设备只能使用类C语言编写的。
4.其他语言已经写好了算法,不想重写,希望直接拿来使用的。
三、使用JNI的准备前提我这里使用的是jdk1.7.0的版本,工作平台是Ubuntu14.0四、使用流程/zyc137********/article/details/6187934第一步需要编写java文件,注意需要加载动态链接库,注意:动态链接库在win32平台下是*.dll,在linux平台下是*.so而且System.loadLibrary("Hello");那么动态链接库的名字必须是libHello.so文件而且该文件需要放在一个/lib文件夹下面(就是放在path目录下面)。
JNI编程注意事项JNI(Java Native Interface)是一种用于在Java中调用本地代码的机制。
在JNI编程中,有一些重要的注意事项需要注意,以确保程序的正确运行和安全性。
以下是一些JNI编程的注意事项:1.正确设置环境变量和路径:在JNI编程之前,需要正确设置环境变量和路径,以确保可以找到所需的本地库和头文件。
这通常涉及到将本地库所在的目录添加到系统的PATH环境变量中,以及将头文件所在的目录添加到Java的INCLUDE环境变量中。
2.使用合适的数据类型:在Java和本地代码之间进行数据传递时,需要使用合适的数据类型。
Java和C/C++之间的数据类型是不同的,需要进行相应的转换。
JNI提供了一些函数来进行数据类型的转换,例如,通过调用`GetStringUTFChars`和`ReleaseStringUTFChars`可以在Java的字符串和C的字符串之间进行转换。
3.进行错误处理:在JNI编程中,需要进行适当的错误处理以处理可能出现的错误情况。
JNI提供了一些函数来获取和处理错误信息,例如,`ExceptionOccurred`和`ExceptionDescribe`函数可以用于捕获并打印异常信息。
在JNI中,必须在Java代码中进行错误处理,并将错误信息传递回Java代码。
4.内存管理:在JNI编程中,需要注意正确管理内存以避免内存泄漏和内存溢出的问题。
JNI提供了一些函数来进行内存管理,例如,`NewGlobalRef`和`DeleteGlobalRef`函数可以创建和删除全局引用,以确保对象在Java和本地代码之间正确传递和删除。
此外,对于使用动态分配的内存,在完成使用后需要进行释放,否则可能会导致内存泄漏。
5.避免耗时操作:在JNI编程中,应尽量避免在本地代码中执行耗时操作,以避免阻塞Java主线程的执行。
如果需要执行耗时操作,可以将其移到单独的线程中执行,并在必要时使用Java的并发机制来进行线程同步和通信。
负责⼈:朔月&futurexiong分任务链接地址:/guide/practices/jni.htmlJNI Tips-JNI技巧JNI是Java本地接⼝(Java Native Interface)的简称。
它定义了托管代码(用Java编程语言写的)与本地代码(用C/C++写的)交互的⼀种方式(译者注:这里的托管代码应该理解成受Java运行时环境监管的代码)。
它与⼚商无关,支持从动态共享库中加载代码,虽然繁琐但有时是合理有效的。
你应该通读JNI spec for J2SE 6来获取对JNI是如何⼯作的以及它有什么可用的功能的⼀个认知。
在你读第⼀遍的时候可能对JNI的某些方面的理解不会立刻就清晰,所以你会发现⼀下的章节可能会对你有所帮助。
JNI Programmer's Guide and Specification里有更为详细的资料。
JavaVM and JNIEnv-JavaVM和JNIEnvJNI定义了2种关键的数据结构,"JavaVM"和"JNIEnv"。
它们本质上都是指向函数表的指针的指针。
(在C++的版本中,它们被定义成类(译者注:准确来说是C++中的结构体),类里面包含⼀个指向函数表的指针,以及与JNI函数⼀⼀对应的用来间接访问函数表的成员函数。
)JavaVM提供了"调用接⼝"的函数,允许你创建和销毁⼀个JavaVM。
理论上每个进程你可以有多个JavaVM,但Android只允许有⼀个。
JNIEnv提供了⼤多数的JNI函数。
你的本地方法都会接收JNIEnv作为第⼀个参数。
JNIEnv用于本地线程存储。
因此,你不能在线程间共享同⼀个JNIEnv。
如果⼀个代码段没有其他方式获取它自身线程的JNIEnv,你可以共享JavaVM,用GetEnv来获取线程的JNIEnv。
(假设这个线程有⼀个JavaVM;参见下面的AttachCurrentThread。
java jni方法Java JNI方法是Java Native Interface的简称,是一种用于在Java程序中调用本地C/C++代码的技术。
JNI方法允许开发者在Java程序中使用底层的本地库函数,实现高性能和跨平台的功能。
本文将为您介绍JNI方法的基本概念、使用方法以及相关注意事项。
JNI方法是Java与本地代码之间进行通信的桥梁。
通过JNI方法,Java程序可以直接调用本地C/C++库中的函数,实现对底层资源的访问,以及实现高性能的计算任务。
JNI方法在开发需要访问底层硬件、操作系统级别的功能、调用系统级别库函数等情况下非常有用。
要使用JNI方法,首先需要在Java代码中声明native关键字。
native关键字告诉编译器这个方法将在本地代码中实现。
然后,在本地代码中实现相应的函数,函数名称要与Java中声明的方法名称一致。
在Java代码中,可以使用`System.loadLibrary("library_name")`方法加载本地库。
这个方法会在本地系统路径中查找并加载指定名称的库文件。
一旦库文件加载成功,就可以通过调用声明为native的Java方法来调用本地代码。
为了在Java代码中调用本地函数,需要使用JNI提供的接口函数。
JNI接口函数提供了一系列函数用于在Java和本地代码之间传递参数、调用本地函数以及处理返回值。
这些函数包括`JNIEnv`和`JavaVM`等。
使用JNI方法需要注意以下几点。
首先,本地代码必须与Java代码在相同的平台以及编译器下进行编译。
其次,在使用JNI方法时,应考虑到跨平台的兼容性,避免使用与特定平台相关的功能。
此外,开发者还需要注意内存管理的问题,避免出现内存泄漏或者内存溢出等问题。
总之,JNI方法为Java开发者提供了一个与本地代码进行交互的桥梁,可以实现更高效、更灵活的功能。
然而,使用JNI方法需要开发者具备一定的本地编程能力,并且注意到与平台和兼容性相关的问题。
Android中JNI的使用方法首先看一下Android平台的框架图:可以看到Android上层的Application和ApplicationFramework都是使用Java编写,底层包括系统和使用众多的LIiraries都是C/C++编写的。
所以上层Java要调用底层的C/C++函数库必须通过Java的JNI来实现。
下面将学习Android是如何通过Jni来实现Java对C/C++函数的调用。
以HelloWorld程序为例:第一步:使用Java编写HelloWorld 的Android应用程序:package com.lucyfyr;import android.app.Activity;import android.os.Bundle;import android.util.Log;public class HelloWorld extends Activity {/** Called when the activity is first created. */@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(yout.main);Log.v("dufresne", printJNI("I am HelloWorld Activity"));}static{//加载库文件System.loadLibrary("HelloWorldJni");}//声明原生函数参数为String类型返回类型为Stringprivate native String printJNI(String inputStr);}这一步我们可以使用eclipse来生成一个App;因为eclipse会自动为我们编译此Java文件,后面要是用到。
JNI编程⼩技巧集合(持续更新)1、java 传⼊的String 在 C 中转化为 char*打印出来jstring obj;const char* string = (char*)(*env)->GetStringUTFChars(env,obj,NULL);__android_log_print(ANDROID_LOG_INFO, "JNIMsg",string);2、'for' loop initial declarations are only allowed in C99 mode 错误int i = 0;for (; i < size; i++) {}需要把int i 定义在前⾯3、取得数组中下标为 i 的元素jobject obj= ((*env)->GetObjectArrayElement(env, array, i));4、JNI定义字符串数组并给字符串数组赋值jobjectArray arrays = 0;//定义长度jsize len = 20;arrays = (*jniEnv)->NewObjectArray(jniEnv, len, (*jniEnv)->FindClass(jniEnv, "java/lang/String"), 0);jstring jstr;char* sa[] = { "Hello,", "world!", "JNI", "很", "好玩" };int i = 0;for (; i < len; i++){jstr = (*env)->NewStringUTF(env, sa[i]);(*env)->SetObjectArrayElement(env, arrays, i, jstr);//必须放⼊jstring}5、获取数组的值int k = 0;for (; k < len; k++) {jstring string = (jstring)((*jniEnv)->GetObjectArrayElement(jniEnv,arrays, k));if (string != NULL) {char * c = (*jniEnv)->GetStringUTFChars(jniEnv, string, 0);__android_log_print(ANDROID_LOG_INFO, "JNIMsg", c);}}6、中间层数据类型转化char* ---> jstring (*jniEnv)->NewStringUTF(jniEnv,char*)jstring ---> char (*jniEnv)->GetStringUTFChars(jniEnv, jstring, 0);long ---> char* ltoa(long,char*,10); sprintf(csendBodyLen,"%ld",sendBodyLen);char* ---> long *long = atol(char*);。
jni thread 用法JNI(Java Native Interface)是一种用于实现 Java 和本地代码(如 C、C++等)交互的桥梁技术。
JNI允许 Java 调用本地代码,也可以将本地代码嵌入到 Java 程序中。
其中,JNI Thread 是 JNI 中一种特殊的线程类型,可以通过 JNI 接口在 Java 和本地代码之间进行线程交互。
本文将介绍 JNI Thread 的使用方法和相关注意事项,内容将包括以下几个方面:1. JNI Thread 的基本概念2. JNI Thread 的创建和销毁3. JNI Thread 中的线程同步机制4. JNI Thread 的异常处理5. 实例演示1. JNI Thread 的基本概念JNI Thread 即 JNI 线程,它是 Java Thread 和本地线程之间的一个桥梁,可以让本地线程调用 Java 方法或回调 Java 代码。
JNI Thread 提供了一种灵活的方式,让 Java 和本地代码可以在不同线程中并发执行。
与普通的 Java Thread 不同,创建和管理 JNI Thread 需要使用JNI 接口函数。
JNI 提供了一系列的函数来创建、销毁和管理JNI Thread,例如:NewThread、AttachCurrentThread、DeattachCurrentThread 等。
2. JNI Thread 的创建和销毁2.1 JNI Thread 的创建要在 JNI 中创建线程,必须通过 JNI 接口函数AttachCurrentThread 将当前的本地线程附加到 JVM 中。
以下是 JNI Thread 的创建过程:```c++JNIEnv* env;JavaVM* jvm;jvm->AttachCurrentThread((void**)&env, NULL, NULL);```2.2 JNI Thread 的销毁当 JNI Thread 结束时,需要通过 JNI 接口函数DetachCurrentThread 将本地线程从 JVM 中分离。
文章来源:csdn 作者:normalnotebook摘要本文为在32 位Windows 平台上实现Java 本地方法提供了实用的示例、步骤和准则。
本文中的示例使用Sun Microsystems 公司创建的Java Development Kit (JDK) 版本1.4.1。
用C 语言编写的本地代码是用Microsoft Visual C++ 编译器编译生成。
简介近日,由于项目需要,要在WEB页面实现图像转换功能,而VC在图像转换方面有着得天独厚的优势。
我们首先用VC封装出图像转换的DLL,然后用JAVA的本地化方法JNI 调用用于图像转换的DLL,最后用JavaBean调用JNI生成的DLL。
通过近几天在网上找资料和自己的摸索,收获很多,现总结如下,让以后做这方面的人少走弯路。
一. JAVA部分1. 无包的情况:实例一:public class MyNative{static{System.loadLibrary( "MyNative" );}public native static void HelloWord();public native static String cT oJava();}说明:1)在JAVA程序中,首先需要在类中声明所调用的库名称System.loadLibrary( String libname );,在库的搜寻路径中定位这个库。
定位库的具体操作依赖于操作系统。
在windows 下,首先从当前目录查找,然后再搜寻”PATH”环境变量列出的目录。
如果找不到该库,则会抛出UnsatisfiedLinkError。
2)这里加载的是JNI生成的DLL,而不是其他生成的DLL的名称。
在这里,库的扩展名字可以不用写出来,究竟是DLL还是SO,由系统自己判断。
3) 还需要对将要调用的方法做本地声明,关键字为native。
并且只需要声明,而不需要具体实现。
实现放在C中实现,稍后将做说明。
4)如果加了static,表明是静态方法。
如果不加,表明是一般的方法。
加与不加,生成的头文件中有一个参数不同。
稍后将做说明。
现在开始编译它:用javac MyNative.h编译它,生成对应的class文件。
用javah MyNative ,就会生成对应的MyNative.h头文件。
剩下的是就开始交给VC来完成了(我们用VC来实现对应的C实现部分)。
2. 有包的情况:实例二:package com..myNative;public class MyNative{static{System.loadLibrary( "MyNative" );}public native static void HelloWord();public native static String cT oJava();}其他与上面相同,就是在用javac和javah时有所不同。
对于有包的情况一定要注意这一点,开始时我的程序始终运行都不成功,问题就出在这里。
javac ./com/myNative/MyNative.javajavah com.myNative.MyNative上面一句就不用解释了。
对下面的一句解释一下:本类的前面均是包名。
这样生成的头文件就是:com.myNative.MyNative.h。
开始时,在这种情况下我用javah MyNative生成的头文件始终是MyNative.h。
在网上查资料时,看见别人的头文件名砸那长,我的那短。
但不知道为什么,现在大家和我一样知道为什么了吧。
:)。
有时还需要带上路径。
具体查看javah的语法。
二.C实现部分刚才用javah MyNative生成的MyNative.h头文件内容如下:/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>/* Header for class MyNative */#ifndef _Included_MyNative#define _Included_MyNative#ifdef __cplusplusextern "C" {#endif/** Class: MyNative* Method: HelloWord* Signature: ()V*/JNIEXPORT void JNICALL Java_MyNative_HelloWord (JNIEnv *, jclass);/** Class: MyNative* Method: cToJava* Signature: ()Ljava/lang/String;*/JNIEXPORT jstring JNICALL Java_MyNative_cToJava (JNIEnv *, jclass);#ifdef __cplusplus}#endif#endif接下来,就是如何实现它了。
其实,用JNI作出的东西也是DLL,被JAVA所调用。
在具体实现的时候,我们只关心两个函数原型:JNIEXPORT void JNICALL Java_MyNative_HelloWord(JNIEnv *, jclass);和JNIEXPORT jstring JNICALL Java_MyNative_cToJava(JNIEnv *,jclass);现在让我们开始激动人心的第一步吧: ) 。
在project里面选择win32 Dynamic-link Library,然后点击下一步,其余的取默认。
如果不取默认的,将会有dllmain()函数。
取空DLL工程的话,将无这个函数。
我在这里取的是空。
然后选择new->File->C++ Source File,生成一个空*.cpp文件。
我们把他取名为MyNative。
把JNIEXPORT void JNICALL Java_MyNative_HelloWord(JNIEnv *, jclass);和JNIEXPORT jstring JNICALL Java_MyNative_cT oJava(JNIEnv *, jclass);拷贝到CPP文件中去。
然后把头文件包含进来。
生成的MyNative.cpp内容如下:#include <stdio.h>#include "MyNative.h"JNIEXPORT void JNICALL Java_MyNative_HelloWord (JNIEnv *env, jclass jobject){printf("hello word!\n");}JNIEXPORT jstring JNICALL Java_MyNative_cToJavaJNIEnv *env, jclass obj){jstring jstr;char str[]="Hello,word!\n";jstr=env->NewStringUTF(str);return jstr;}在编译前一定要注意下列情况。
注意:一定要把SDK中的include文件夹中(和它下面的win32文件夹下的头文件)的几个头文件拷贝到VC的include文件夹中。
或者在VC的tools\options\directories中设置,把头文件给包含进来。
对程序的一点解释:1)前文不是说过,加了static和不加只是一个参数的区别吗。
就是jclass的不同,不加static这里就是jobject。
也就是JNIEXPORT void JNICALLJava_MyNative_HelloWord(JNIEnv *env, jobject obj)。
2)这里JNIEXPORT和JNICALL都是JNI的关键字,表示此函数是要被JNI调用的。
而jstring是以JNI为中介使JAVA的String类型与本地的string沟通的一种类型,我们可以视而不见,就当做String使用(具体对应见表一)。
函数的名称是JAVA_再加上java程序的package路径再加函数名组成的(参见有包的情况)。
参数中,我们也只需要关心在JAVA 程序中存在的参数,至于JNIEnv*和jclass我们一般没有必要去碰它。
3)NewStringUTF()是JNI函数,从一个包含UTF格式编码字符的char类型数组中创建一个新的jstring对象。
4) 以上程序片断jstr=env->NewStringUTF(str);是C++中的写法,不必使用env指针。
因为JNIEnv函数的C++版本包含有直接插入成员函数,他们负责查找函数指针。
而对于C 的写法,应改为:jstr=(*env)->NewStringUTF(env,str);因为所有JNI函数的调用都使用env 指针,它是任意一个本地方法的第一个参数。
env指针是指向一个函数指针表的指针。
因此在每个JNI函数访问前加前缀(*env)->,以确保间接引用函数指针。
在C和Java编程语言之间传送值时,需要理解这些值类型在这两种语言间的对应关系。
这些都在头文件jni.h中,用typedef语句声明了这些类在目标平台上的代价类。
头文件也定义了常量如:JNI_FALSE=0 和JNI_TRUE=1;表一说明了Java类型和C类型之间的对应关系。
表一Java类型和C类型Java编程语C编程语字节言言boolean jboolean 1byte jbyte 1char jchar 2short jshort 2int jint 4long jlong 8float jfloat 4double jdouble 8现在开始对所写的程序进行编译。
选择build->rebuild all对所写的程序进行编译。
点击build->build MyNative.DLL生成DLL文件。
也可以用命令行cl来编译。
具体参看其他书籍。
再次强调(曾经为这个东西大伤脑筋):DLL放置地方1) 当前目录。
2) 放在path所指的路径中3) 自己在path环境变量中设置一个路径,要注意所指引的路径应该到.dll文件的上一级,如果指到.dll,则会报错。
下面就开始测试我们的所写的DLL吧(假设DLL已放置正确)。
public class mytest{public static void main(String[] args){MyNative a=new MyNative();a.HelloWord();System.out.println(a.cToJava());}}注意也要把MyNative.class放在与mytest.java同一个路径下。