JNI学习系列(一)

来源:互联网 发布:python中文编码问题 编辑:程序博客网 时间:2024/05/01 09:41

最近在工作的开发过程中需要使用到JNI,但之前对于这块了解不够,因此恶补了一阵子,终于搞定了。好记性不如烂笔头,就顺便把一些关于JNI的开发整理出来,顺便增强自己的记忆,

1、 JNI背景介绍:

JNI(Java nativeinterface)是为了方便Java去调用C/C++实现的接口和方法的机制。Java是一种和平台无关的语言,而android是基于linux的的操作系统,只对上层应用提供C/C++的接口和方法,需要通过JNI把Java和C/C++连接起来。

Java通过JNI调用本地方法,而本地方法以库的形式保存在平台中。通过调用本地方法的实现,就可以将Java和系统调用联系起来,调用系统的一些模块、库进行交互。

1) 执行效率

    对比C/C++与java的执行效率,主要是由于C/C++是编译型的语言,而java语言是解释性的语言,需要将java语言解释为二进制语言代码,计算机才能识别并运行。对于涉及大量运算的时候C/C++的执行效率会由于Java的执行效率。

2) 硬件控制

目前对于硬件设备的控制,目前大部分的设备的driver都是C实现了,通过JNI就可以实现Java对硬件设备的控制。


简单来说,JNI可以分为两部分java编程任务和C/C++编程任务的,这样可以让java部分和C/C++部分的工程师分别开发。由于之前学习的android应用开发忘得差不多了,为了顺便进行学习一下,所以就那android应用来

实现JNI的步骤大致可以分为六步:

Step1:编写java部分的本地方法;声明java中的本地方法,指定加载的lib文件,调用本地方法(在本例中通过android apk中事件响应来实现);

Step2:编译java部分的代码;需要将定义的java代码编译生成字节码,以便后续生产头文件;

Step3:创建C/C++的本地函数头文件;由于Java需要调用C/C++中的方法,因此需要在C/C++中声明方法,并进行定义。

Step4:编写C/C++本地函数的实现;实现本地函数的功能。

Step5:生成JNI的lib库文件;编译C/C++中实现的本地函数,生产lib文件(本例在linux平台运行,因此生产的为*.so文件);

Step6:运行java测试程序。查看运行的节目。

 

 

2、 JNI实现(step1):

首先看一下在java环境中对于JNI有关方法部分的code的编写

1) Java的代码中native方法的声明:

package com.led.api;import android.R.bool;public class LedNative {static{       System.loadLibrary("LedJni");//Tip 1 加载对应的JNI库,LedJni是JNI库的名字,在实际加载动态库的时候会进行扩展为libLedJni.so       System.out.println("library path"+System.getProperty("java.library.path"));      }public native static bool ledPowerOn(); //Tip2 声明一个native函数,声明为此方法的实现有native层实现public native static bool ledPowerOff();}


Java中本地方法的定义,在java类中,通过“native”关键字来声明本地方法。“native”关键字告知java编译器,在java中该方法仅声明,具体的实现由C/C++来实现。

如果没有增加native关键字则会提示函数需要实现“This method requires a body instead of a semicolon”。


其中System.loadLibrary("com_tcl_tv_jni");为java中加载具体实现本地方法的lib库文件,"com_tcl_tv_jni"为libcom_tcl_tv_jni.so,在loadLibrary中需要去掉“lib”和“.so”字符。为了保证能够在本地方法调用加加载本地方法的库文件,通常将System.loadLibrary调用放在本地方法声明的静态块中,避免在调用本地方法在加载库之前导致异常错误。

 2)在应用中如何调用native方法

Android apk调用部分的code:

package com.led.control;import com.led.api.LedNative;   //Tip1 import对应的native类import android.app.Activity;import android.os.Bundle;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;public class LedControlActivity extends Activity {    /** Called when the activity is first created. */    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);                Button powerOn = (Button)this.findViewById(R.id.On);        Button poerOff = (Button)this.findViewById(R.id.Off);                powerOn.setOnClickListener(new OnClickListener(){public void onClick(View v) {// TODO Auto-generated method stubLedNative.ledPowerOn(); //Tip2 由于native方法声明为static,所以可以通过类名直接方法;如果为非static需要通过对象方法}                });                poerOff.setOnClickListener(new OnClickListener(){public void onClick(View v) {// TODO Auto-generated method stubLedNative.ledPowerOff();}});    }}

3) 编译java文件(step2)

编译android工程在bin目录下生产对应的字节码文件,以及对应的apk。



Java的native部分的总结

从上面的代码部分可以看出来,ledPowerOn和ledPowerOff函数前面都通过native关键字来声明,表明该函数需要在native层来实现

1)需要加载对应的lib库

2)需要使用关键字native方法类声明对应的函数。

原创粉丝点击