一、JNI简介
JNI:Java Native Interface,是Java语言提供的一种通用接口,用于Java代码与本地化代码的交互。所谓本地化代码是指直接编译成的与机器相关的二进制代码,而非Java字节码之类的中间代码。Windows下面的可执行文件,DLL等,Linux下面的可执行文件和SO文件等,都是二进制代码。
JNI允许Java语言编写的程序与其他语言编写的程序库(DLL, SO)或可执行文件进行互操作,包括汇编、C、C++。JNI产生的原因在于以下几种需求:
(1). 你的应用程序需要使用系统相关的功能,而Java代码不支持或是难以办到。这个比较典型的是实现托盘图标,有几种现成的方案都是用的JNI做的,名字好像是叫做TrayIcon和StayOnTop。当然啦,如果是用的Java1.6,那就要另当别论了。
(2). 已有其他语言写好的类库或程序,希望Java程序可以使用它们。
(3). 出于更高的性能要求,希望使用汇编或是C/C++语言来实现部分功能。
下图出自JNI Tutorial,展示了JNI的地位:
其他的理论的东西就不多说了,JNI Tutorial讲得很清楚。强烈建议阅读。
二、JNI的开发步骤
这里以使用C++编写本地化方法实现为例,开发一个使用JNI的Demo程序,具体步骤如下所示:
(1). 编写带有native方法的java类
(2). 使用javac命令编译所编写的java类
(3). 使用javah命令处理类文件,生成C/C++头文件
(4). 使用C/C++实现本地方法
(5). 将C/C++编写的文件生成动态连接库
三、Demo程序,Demo程序宣示了Java代码中调用C++的输出功能打印字符串,同时演示了使用C++的输入功能读取字符串,并使用System.out.println输出。
1. 编写带native方法的Java类
本示例中的源程序就一个Java类。如下所示:
// HelloJNI.java -- 简单的JNI入门示例。
// 2007-4-5 16:41:45
public class HelloJNI {
public native void displayHello();
public native void showTime();
private native String getLine(String prompt);
static {
System.loadLibrary("hello");
}
public static void main(String[] args) throws Exception {
HelloJNI hj = new HelloJNI();
System.out.println("==> Demo 1: hello");
hj.displayHello();
System.out.println("==> Demo 2: time");
hj.showTime();
System.out.println("==> Demo 3: input");
String input = hj.getLine("Type a line: ");
System.out.println("User typed: " + input);
}
}
说明:一共3个native方法,第一个简单的Hello,第二个使用<ctime>头文件中的相关函数计算当前时间,第三个读取输入。注意static语句块:
static {
System.loadLibrary("hello");
}
在JVM载入HelloJNI类的时候加载动态库,System.loadLibrary()中的参数是我们要生成的动态库文件的名字,不包括扩展名,在Windows下面是hello.dll,Linux下面是hello.so,这个由Java自动识别。
2. 编译此类
3. javah HelloJNI 生成C/C++头文件,生成的头文件不用任何修改。如下所示:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class HelloJNI */
#ifndef _Included_HelloJNI
#define _Included_HelloJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: HelloJNI
* Method: displayHello
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_HelloJNI_displayHello
(JNIEnv *, jobject);
/*
* Class: HelloJNI
* Method: showTime
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_HelloJNI_showTime
(JNIEnv *, jobject);
/*
* Class: HelloJNI
* Method: getLine
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_HelloJNI_getLine
(JNIEnv *, jobject, jstring);
#ifdef __cplusplus
}
#endif
#endif
4. 编写C/C++实现文件,如下所示:
// HelloJNIImpl.cpp -- 自己编写的实现文件
// 2007-4-5 16:52:53
#include <jni.h>
#include <iostream>
#include <ctime>
#include <string>
#include <cstdio>
#include <windows.h>
#include "HelloJNI.h"
extern "C" {
//
}
using namespace std;
JNIEXPORT void JNICALL Java_HelloJNI_displayHello(JNIEnv * env, jobject obj) {
cout << "Hello, JNI tech. This is from C++!" << endl;
}
JNIEXPORT void JNICALL Java_HelloJNI_showTime(JNIEnv * env, jobject obj) {
time_t sec;
tm t;
time_t loop;
cout << "时间:";
sec = time(NULL);
t = *localtime(&sec);
unsigned int hour = t.tm_hour;
unsigned int mini = t.tm_min;
unsigned int secd = t.tm_sec;
if(hour < 10) {
cout << "0" << hour;
}
else {
cout << hour;
}
cout << ":";
if(mini < 10) {
cout << "0" << mini;
}
else {
cout << mini;
}
cout << ":";
if(secd < 10) {
cout << "0" << secd;
}
else {
cout << secd;
}
cout << endl;
}
JNIEXPORT jstring JNICALL Java_HelloJNI_getLine(JNIEnv * env, jobject obj, jstring prompt) {
char buf[128] = {0};
const char * str = (env)->GetStringUTFChars(prompt, 0);
// printf("%s", str);
cout << str;
(env)->ReleaseStringUTFChars(prompt, str);
string buffer;
getline(cin, buffer);
// scanf("%s", buf);
return (env)->NewStringUTF(buffer.c_str());
}
说明:JNI Tutorial中使用的居然是像下面这样的代码,env指针的使用应该有误,敬请注意。
JNIEXPORT jstring JNICALL
Java_Prompt_getLine(JNIEnv *env, jobject obj, jstring prompt)
{
char buf[128];
const char *str = (*env)->GetStringUTFChars(env, prompt, 0);
printf("%s", str);
(*env)->ReleaseStringUTFChars(env, prompt, str);
...
5. 生成本地库文件。笔者使用的VS.NET 2003中的C++编译器。VS.NET 2003命令行工具生成DLL的命令:
cl -I<头文件目录1> -I<头文件目录2> -LD <C/C++源文件名> -Fe<生成的DLL文件名>
-I选项指定头文件目录,-LD指定C++源文件,-Fe指定生成的DLL文件名。将各个部分替换成实际的情况,实际使用的命令如下:
cl -IC:/java/jdk1.5.0_10/include -IC:/java/jdk1.5.0_10/include/win32 -LD HelloJNIImpl.cpp -Fehello.dll
注:cl可以增加-EHsc参数来减少生成过程中的输出信息。如下图所示:
6. 运行结果,如下图所示:
注意自己输入的那一行!
7. 自动化。其实步骤都很简单,所以可以使用Ant来完成。下面提供一个ANT Buildfile。使用之前请根据自己的实际情况修改相关属性。
注意:Builfile编码是UTF-8的。
build.xml
<?xml version="1.0" encoding="UTF-8"?>
<project default="help" basedir="." name="JNI_Hello">
<property name="app.home" value="."></property>
<!-- 设置头文件的目录,根据JDK具体的安装目录而定 -->
<property name="h.dir1" value="C:/java/jdk1.5.0_10/include"></property>
<property name="h.dir2" value="C:/java/jdk1.5.0_10/include/win32"></property>
<!-- 设置cl工具的路径,视具体情况而定 -->
<property name="vc.bin.dir"
value="C:/Program Files/Microsoft Visual Studio .NET 2003/Vc7/bin">
</property>
<property name="cpp.name" value="HelloJNIImpl.cpp"></property>
<property name="dll.name" value="hello.dll"></property>
<target name="compile" description=" ==> 编译Java源文件">
<javac srcdir="${app.home}" destdir="${app.home}">
</javac>
</target>
<target name="javah" description=" ==> 生成C/C++头文件">
<javah destdir="${app.home}" force="yes" class="HelloJNI"/>
</target>
<target name="dll" description=" ==> 调用cl命令生成相关的DLL文件">
<exec dir="${app.home}" executable="${vc.bin.dir}/cl.exe" os="Windows XP">
<!-- 参数-EHsc好像是VS.NET2003中cl.exe的,可以不加,参考下面的注释行 -->
<arg line="-EHsc -I${h.dir1} -I${h.dir2} -LD ${cpp.name} -Fe${dll.name}"/>
<!--
<arg line="-I${h.dir1} -I${h.dir2} -LD ${cpp.name} -Fe${dll.name}"/>
-->
</exec>
</target>
<target name="run" description=" ==> 运行">
<java classname="HelloJNI"></java>
</target>
<target name="all" description=" ==> 自动进行上面任务列表">
<antcall target="compile"/>
<antcall target="javah"/>
<antcall target="dll"/>
<antcall target="run"/>
</target>
<target name="help" description=" ==> 显示帮助信息">
<echo>用法帮助:</echo>
<echo>ant compile 编译Java源文件</echo>
<echo>ant javah 生成C/C++头文件</echo>
<echo>ant dll 调用cl命令生成相关的DLL文件</echo>
<echo>ant run 运行</echo>
<echo></echo>
<echo>ant all 自动进行上面任务列表</echo>
<echo>ant help 显示帮助信息</echo>
</target>
</project>
Done!^_^!
JNI还有很多高级的功能,这里我就不说了,一来是不太会,二来也没什么意义。JNI Tutorial上讲得很全面,不错。
分享到:
相关推荐
### JNI入门实例详解 #### 一、JNI简介 JNI(Java Native Interface)是Java平台标准的一部分,它允许Java代码和其他语言编写的代码进行交互。这里的“其他语言”通常指的是C和C++这样的本地代码。通过JNI,Java...
这个入门实例将带你了解如何使用JNI在Java程序中调用C或C++的原生代码,以及如何处理返回的结果。 一、JNI基础概念 JNI是一种规范,它定义了Java虚拟机(JVM)与本地代码(如C、C++)之间的接口。通过JNI,Java...
通过以上步骤,你已经成功实现了Android Studio中的JNI编程入门。然而,这只是基础,实际开发中可能需要处理更复杂的情况,如多线程、内存管理、错误处理等。同时,CMakeLists.txt作为现代的构建系统,提供了更多...
Android Studio的JNI(Java Native Interface)开发入门教程 JNI,全称为Java Native Interface,是Java平台标准的一部分,它允许Java代码和其他语言写的代码进行交互。JNI在Android开发中扮演着重要角色,尤其当...
通过学习和实践这个JNI入门Demo1.0,你可以掌握JNI的基本用法,包括声明`native`方法、生成头文件、编写C++代码以及构建和加载动态库。这将为你进一步探索Android的原生开发打下基础,比如使用C++提升性能、接入第三...
### JNI入门初级教程知识点概述 本教程旨在为初学者提供JNI(Java Native Interface)的基础知识与实践指导。JNI是Java平台的一部分,它允许Java代码与其他语言编写的代码进行交互,尤其是C和C++。这对于利用现有C...
jni快速入门实例,java文件里写了几个函数,参数包含了常用的数据类型、类、数组等。对应的有C的实现和C++的实现,并且两者混编在一起,生成一个so。有Makefile。基本上涵盖了jni开发用到的基本技术。原创资源。
这篇“JNI入门教程之HelloWorld篇”文档将引导我们了解如何使用JNI来开发一个简单的应用程序。 首先,我们需要明白JNI的核心概念:本地方法接口。它提供了一种方式,让Java虚拟机(JVM)能够调用非Java语言编写的...
- **直接调用**:通过JNIEnv指针,可以调用Java的静态和实例方法,包括同步和异步方法。 - **回调Java方法**:本地代码可以通过`CallVoidMethod`, `CallNonvirtualVoidMethod`等函数,回调Java对象的方法。 7. **...
在这个"Android jni 编程实例"中,我们将探讨如何在Android Studio环境下进行JNI开发,通过一个简单的入门demo来学习这个过程。 首先,我们需要了解JNI的基本概念。JNI是Java平台提供的一种接口,它允许Java代码...
### JNI的简单入门实例 JNI(Java Native Interface)是一种标准的接口规范,它允许Java代码与其他语言编写的代码进行交互,比如C、C++等。JNI对于开发高性能应用或者调用本地库非常有用。下面将根据提供的文件内容...
本教程将带你入门JNI,了解如何在Java中调用C代码,以及C代码如何回调Java。 首先,我们要创建一个Java类,声明一些本地方法(native methods)。本地方法是Java方法,但其实现是在C或C++中完成的。例如: ```java...
在这个例子中,`displayHelloJni`是一个使用`native`关键字声明的原生方法。`System.loadLibrary`用于加载名为`helloJni`的本地库,这个库中包含了与`displayHelloJni`相对应的本地实现。这样,当Java程序运行时,就...
JNI的入门开发,其中包含我个人的理解和实例,肯定对大家有帮助、 很好的学习例子
### JNI开发入门1 #### 一、概述 JNI(Java Native Interface)是Java平台标准的一部分,它允许Java代码与其他语言写的代码进行交互。JNI的主要作用是让Java程序能够调用本地应用程序或者库(通常指C/C++语言编写...
在提供的压缩包`myJni`中,很可能包含了一个简单的JNI实例,比如一个简单的"Hello, World!"程序,或者是演示如何从Java调用C++函数的例子。通过学习这个实例,初学者可以更好地理解如何在Android应用中集成本地代码...
本实例源码"hellojni"是一个典型的NDK和JNI的入门示例,它将帮助我们理解如何在Android项目中集成和使用本地代码。 1. **NDK**:NDK是一套工具集,它提供了编译、构建和运行原生代码的环境。通过NDK,开发者可以在...
在"jni-helloWorld"这个项目中,我们看到的是一个JNI的入门示例,主要目的是帮助开发者理解如何使用JNI来调用本地(非Java)代码。 首先,"HelloWorld"是编程中的经典例子,通常用于展示一种新语言或技术的基本用法...
《Android NDK与JNI开发详解:从Hello-JNI入门》 Android系统以其开源性和灵活性吸引了大量的开发者,而JNI(Java Native Interface)则是Android平台中连接Java层与原生C/C++代码的重要桥梁。JNI允许开发者在...
JNI是java调用C++程序的一种实现方法,网上有一些相关的资料,但不一定能适用,这个文档我在学习JNI时综合网上资料总结的,本人亲测能够实现,希望下载的网友有什么问题多多反馈,希望对学习JNI的朋友有所帮助