java JNI编程指南 下载本文

上面的都是基本类型。如果Java函数的参数是class,则以\开头,以\结尾,中间是用\隔开的包及类名。而其对应的C函数名的参数则为jobject. 一个例外是String类,其对应的类为jstring

Ljava/lang/String; String jstring Ljava/net/Socket; Socket jobject

如果JAVA函数位于一个嵌入类,则用$作为类名间的分隔符。 例如 \

Android JNI编程实践

一、直接使用java本身jni接口(windows/ubuntu)

1.在Eclipsh中新建一个android应用程序。两个类:一个继承于Activity,UI显示用。另一个包含native方法。编译生成所有类。 jnitest.java文件:

package com.hello.jnitest;

import android.app.Activity; import android.os.Bundle;

public class jnitest extends Activity {

/** Called when the activity is first created. */ @Override

public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);

setContentView(R.layout.main);

Nadd cal = new Nadd();

setTitle(\ } }

Nadd.java文件:

package com.hello.jnitest;

public class Nadd {

static {

System.loadLibrary(\ }

public native int nadd(int a, int b); }

以上在windows中完成。

2.使用javah命令生成C/C++的.h文件。注意类要包含包名,路径文件夹下要包含所有包中的类,否则会报找不到类的错误。classpath参数指定到包名前一级文件夹,文件夹层次结构要符合java类的组织层次结构。

javah -classpath ../jnitest/bin com.hello.jnitest.Nadd com_hello_jnitest_Nadd .h文件:

/* DO NOT EDIT THIS FILE - it is machine generated */ #include

/* Header for class com_hello_jnitest_Nadd */

#ifndef _Included_com_hello_jnitest_Nadd #define _Included_com_hello_jnitest_Nadd #ifdef __cplusplus extern \#endif /*

* Class: com_hello_jnitest_Nadd * Method: nadd * Signature: (II)I */

JNIEXPORT jint JNICALL Java_com_hello_jnitest_Nadd_nadd (JNIEnv *, jobject, jint, jint);

#ifdef __cplusplus }

#endif #endif

3.编辑.c文件实现native方法。 com_hello_jnitest_Nadd.c文件: #include

#include \

JNIEXPORT jint JNICALL Java_com_hello_jnitest_Nadd_nadd(JNIEnv * env, jobject c, jint a, jint b) {

return (a+b); }

4.编译.c文件生存动态库。 arm-none-linux-gnueabi-gcc -I/home/a/work/android/jdk1.6.0_17/include -I/home/a/work/android/jdk1.6.0_17/include/linux -fpic -c com_hello_jnitest_Nadd.c arm-none-linux-gnueabi-ld

-T/home/a/CodeSourcery/Sourcery_G++_Lite/arm-none-linux-gnueabi/lib/ldscripts/armelf_linux_eabi.xsc -share -o libNadd.so com_hello_jnitest_Nadd.o 得到libNadd.so文件。 以上在ubuntu中完成。

5.将相应的动态库文件push到avd的system/lib中:adb push libNadd.so /system/lib。若提示Read-only file system错误,运行adb remount命令,即可。 Adb push libNadd.so /system/lib

6.在eclipsh中运行原应用程序即可。 以上在windows中完成。

对于一中生成的so文件也可采用二中的方法编译进apk包中。只需在工程文件夹中建libs\\armeabi文件夹(其他文件夹名无效,只建立libs文件夹也无效),然后将so文件拷入,编译工程即可。

二.使用NDK生成本地方法(ubuntu and windows)

1.安装NDK:解压,然后进入NDK解压后的目录,运行build/host-setup.sh(需要Make 3.81和awk)。若有错,修改host-setup.sh文件:将#!/bin/sh修改为#!/bin/bash,再次运行即可。 2.在apps文件夹下建立自己的工程文件夹,然后在该文件夹下建一文件Application.mk和项project文件夹。

Application.mk文件:

APP_PROJECT_PATH := $(call my-dir)/project APP_MODULES := myjni

3.在project文件夹下建一jni文件夹,然后新建Android.mk和myjni.c。这里不需要用javah生成相应的.h文件,但函数名要包含相应的完整的包、类名。 4.编辑相应文件内容。 Android.mk文件:

# Copyright (C) 2009 The Android Open Source Project #

# Licensed under the Apache License, Version 2.0 (the \# you may not use this file except in compliance with the License. # You may obtain a copy of the License at #

# http://www.apache.org/licenses/LICENSE-2.0 #

# Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an \

# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. #

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := myjni LOCAL_SRC_FILES := myjni.c

include $(BUILD_SHARED_LIBRARY)

myjni.c文件:

#include #include

jstring

Java_com_hello_NdkTest_NdkTest_stringFromJNI( JNIEnv* env,

jobject thiz ) {

return (*env)->NewStringUTF(env, \}

myjni文件组织:

a@ubuntu:~/work/android/ndk-1.6_r1/apps$ tree myjni myjni

|-- Application.mk `-- project |-- jni

| |-- Android.mk | `-- myjni.c `-- libs

`-- armeabi

`-- libmyjni.so

4 directories, 4 files

5.编译:make APP=myjni.

以上内容在ubuntu完成。以下内容在windows中完成。当然也可以在ubuntu中完成。 6.在eclipsh中创建android application。将myjni中自动生成的libs文件夹拷贝到当前工程文件夹中,编译运行即可。 NdkTest.java文件:

package com.hello.NdkTest;

import android.app.Activity; import android.os.Bundle;

import android.widget.TextView;

public class NdkTest extends Activity {

/** Called when the activity is first created. */ @Override

public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); TextView tv = new TextView(this); tv.setText( stringFromJNI() ); setContentView(tv); }

public native String stringFromJNI();

static {

System.loadLibrary(\ } }

对于二中生成的so文件也可采用一中的方法push到avd中运行。 序

这四种情况下你会用到本书:

1、 在Java程序中复用以前写过的C/C++代码。 2、 自己实现一个java虚拟机

3、 学习不同语言如何进行协作,尤其是如何实现垃圾回收和多线程。 4、 把一个虚拟机实现整合到用C/C++写的程序中。

本书是写给开发者的。JNI在1997年第一次发布,本书总结了SUN工程师和大量开发者两年来积累的经验。

本书介绍了JNI的设计思想,对这种思想的理解是使用JNI的各种特性的基础。 本书有一部分是JAVA2平台上面的JNI特征的规范说明。JNI程序员可以把这部分用作一个手册。JVM开发者在实现虚拟机的时候必须遵守这些规范。

JNI的部分设计思想来源于Netscape的Java Runtime Interface(JRI)。

第一章 简介

JNI是JAVA平台的一个重要特征,使用它我们可以重用以前用C/C++写的大量代码。本书既是一个编程指南也是一个JNI手册。本书共包括三部分:

1、 第二章通过一个简单的例子介绍了JNI。它的对象是对JNI不熟悉的初学者。

2、 3~10章对JNI的特征进行了系统的介绍。我们会举大量的例子来说明JNI的各个特征,

这些特征都是JNI中重要且常用的。

3、 11~13章是关于JNI的技术规范。可以把这两章当作一个手册。

本书尽量去满足各类读者的需要。指南面向初学者,手册面向有经验的人和自己实现JNI规范的人。大部分读者可能是用JNI来写程序的开发者。本书会假设你有JAVA,C/C++基础。

本章的剩余部分介绍了JNI的背景,扮演的角色和JNI的演化。

1.1 JAVA平台和系统环境(Host Environment)

系统环境代指本地操作系统环境,它有自己的本地库和CPU指令集。本地程序(Native Applications)使用C/C++这样的本地语言来编写,被编译成只能在本地系统环境下运行的二进制代码,并和本地库链接在一起。本地程序和本地库一般地会依赖于一个特定的本地系统环境。比如,一个系统下编译出来的C程序不能在另一个系统中运行。