Java 本地方法 1、初步认识

本地方法,就是在Java虚拟机中调用二进制文件,Android的JNI调用用的也是Java的这一套,因此有必要好好来学习一下。

主要参考 《Java核心技术:卷 II 高级特性》

一、从Java中调用C函数

1、Java层代码:

在Android编程中,这也是本地方法最为常用的一块内容,在Java中,使用native关键字表示本地方法,提示该方法是在外部定义。本地方法不包括代码,直接用分号结束。如:在Fruit.java,代码如下:

package NativeMethod;

public class Fruit {
	public static native void hello();
}

此处的本地方法,我们使用的是静态的,其实本地方法既可以是静态的,也可以是非静态的。区别?

该类可以编译,但现在还无法被调用,否则会提示找到函数的错误。

2、C本地代码:

为了使得我们的程序能够被Java中被调用,我们必须按照Java本地方法的原则来书写函数,规则为:

我们的工程的目录为

包名(NativeMethod),该包下面有Fruit.java和TestNativeMethod.java两个文件

1)使用完整的Java的方法名字,包含包名,比如是 Fruit.java下面的 hello()方法,则应该是 NativeMethod.Fruit.hello

2)使用下划线代替所有的句号,并加上Java前缀,即 Java_NativeMethod_Fruit_hello

3)如果类名中有非ASCII字母或者数字,如:’_’,’$’等,或者大于’\u007F’的字符,则用 _0xxxx代替,其中xxxx为4个十六进制数。

Tips:

如果重载本地方法,那么相同的名字提供多个本地方法的话,需要在名称后面附加两个下划线,后面再加上已经编码的参数类型,如有一个本地方法greeting和greeting(int repeat) ,那么第一个 为 _greeting__ 另外一个为 _greeting__I.

这些工作无需手工完成,可以使用javah工具。以上述我们的程序为例。

<1>首先cd到我们的包名所在的文件夹

$ ls
NativeMethod  Serializable

<2>编译我们的Fruit.java,

javac NativeMethod/Fruit.java

 <3>使用javah生成头文件

javah NativeMethod.Fruit

需要注意的是,此处不是指定指定目录找到类的文件,而是在前面提到的头文件格式中的第一步那样,指明类的完整名字,包含包名,此处我们的包名是NativeMethod,方法名是Fruit,因此调用的是 javah NativeMethod.Fruit

生成的文件NativeMethod_Fruit.h

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class NativeMethod_Fruit */

#ifndef _Included_NativeMethod_Fruit
#define _Included_NativeMethod_Fruit
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     NativeMethod_Fruit
 * Method:    hello
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_NativeMethod_Fruit_hello
  (JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif
#endif

<4>编辑C代码

#include "NativeMethod_Fruit.h"
#include <stdio.h>

JNIEXPORT void JNICALL Java_NativeMethod_Fruit_hello
  (JNIEnv * env, jclass cl){
	printf("Hello World!\n");
}

<5>生成动态连接库

gcc -fPIC -I /home/happyhls/tools/jdk1.7.0_25/include/ -I /home/happyhls/tools/jdk1.7.0_25/include/linux/ -shared -o libNativeMethod_Fruit.so NativeMethod_Fruit.c

其中,-fPIC命令为使用PIC动态连接,是动态连接方式的一种。 -I引入头文件, -shared生成动态连接库

<6>编写测试代码

package NativeMethod;

public class TestNativeMethod {

	public static void main(String[] args){
		Fruit.hello();
	}

	static{
		System.loadLibrary("NativeMethod_Fruit");
	}
}

 <7>运行即可。

java -Djava.library.path=. NativeMethod/TestNativeMethod
Hello World!

注意的是,此处需要引入环境变量,所以运行时使用-D选项

方法有两种

1、export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH

2、java -Djava.library.path=. 运行路径

 

About: happyhls


发表评论

电子邮件地址不会被公开。 必填项已用*标注