`
wsql
  • 浏览: 11792235 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
文章分类
社区版块
存档分类
最新评论

Java JNI Programming基础 1.

 
阅读更多

一、JNI 的特点:

JNI有一个很重要的优点,就是在你充分利用Java的跨平台特性的前提下,你仍然可以利用其它编程语言。JNI是JVM实现很重要的一部分,是允许Java应用调用本地代码(native code)或本地代码调用Java应用的一个双向接口。下图就显示了这两者之间的关系:

JNI支持两种类型的native code: 本地库和本地应用程序
1. 你可以使用JNI写出本地方法,允许Java程序调用由本地方法实现的函数,这在jvm的实现里有大量的应用。我们从jdk的源码里也可以看到大量的这种示例。
2. JNI还支持调用接口(invocation interface),它允许你在本地应用程序(通常是C/C++代码编写)里嵌入jvm的实现,本地应用可以链接实现了jvm的本地库,接着使用调用接口来调用Java中的一些类的方法。比如,使用C编写的Web浏览器,可以执行一个applet代码片段。
总之一句话,JNI建立了Java语言和native code之间的一种双向调用关系。

下面我们看看,一个简单的jni程序如何编写?

二、简单示例:

示例1: HelloWorld.java, 即调用一个C函数,打印一个简单的字符串
packagejnitest;
publicclassHelloWorld...{
publicHelloWorld()...{
}

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

publicnativevoiddisplayHelloWorld();
publicnativevoiddisplayString(Stringsz);
publicnativeStringechoString(Stringsz);

publicstaticvoidmain(String[]args)...{
HelloWorldhelloworld
=newHelloWorld();
Stringt
=helloworld.echoString("测试一下中文");
System.out.println(t);
}

}
Sysem.loadLibrary在static段里,表示在类HelloWorld初始化时,动态加载一个动态库,win32里这个库名应该叫helloworld.dll。这样任何一个HelloWorld实例都可以动态调用helloworld.dll中的方法了。
第一步,我们先build出class文件。
第二步,针对上边的jnitest.class文件,使用javah为其生成C代码中的头文件
cd E:/java/jbproject/jnitest/classes
javah jnitest.HelloWorld
这时我们可以看到生成的头文件名叫jnitest_HelloWorld.h,它的内容如下:
/**//*DONOTEDITTHISFILE-itismachinegenerated*/
#include
<jni.h>
/**//*Headerforclassjnitest_HelloWorld*/

#ifndef_Included_jnitest_HelloWorld
#define_Included_jnitest_HelloWorld
#ifdef__cplusplus
extern"C"...{
#endif
/**//*
*Class:jnitest_HelloWorld
*Method:echoString
*Signature:(Ljava/lang/String;)Ljava/lang/String;
*/

JNIEXPORTjstringJNICALLJava_jnitest_HelloWorld_echoString
(JNIEnv
*,jobject,jstring);

#ifdef__cplusplus
}

#endif
#endif
需要说明的是,
#ifdef__cplusplus
extern"C"...{
#endif
}
表示该头文件也可以用于C++代码的make和link。
下面,我们可以写出本地方法
Java_jnitest_HelloWorld_echoString的实现了。
第二步:实现本地方法.
在刚才的目录
E:/java/jbproject/jnitest/classes下边,我们新建一个文件helloworldimp.cpp。内容如下:
#include<jni.h>
#include
"jnitest_HelloWorld.h"
#include
<stdio.h>

JNIEXPORTjstringJNICALLJava_jnitest_HelloWorld_echoString
(JNIEnv
*env,jobjectobj,jstringsz)
...{
returnsz;
}
这里采用最简单的实现,直接将参数sz的值返回,不作任何改变。

第三步:是build出动态库helloworld.dll,希望你的机器里已经安装好了VC6或者VC7/8(VS2002,2003或者2005)。这里以VC6.0为例,并且采用命令行方式来build。进入到VC的安装目录,这里是D:/msdev/VC98/Bin
编译命令cl就在此目录下边,这个目录下边有个环境变量的批处理文件VCVARS32.bat,我们拿来改一下就可以用了。
在这里,我为它专门加入了jni要使用的头文件,为了编译java代码,把java的ClassPath也加进来了。其内容如下:
@echooff
rem
rem
RootofVisualDeveloperStudioCommonfiles.
setVSCommonDir=D:msdev

rem
rem
RootofVisualDeveloperStudioinstalledfiles.
rem
setMSDevDir=D:msdevCommonmsdev98

rem
rem
RootofVisualC++installedfiles.
rem
setMSVCDir=D:msdevVC98

rem
rem
VcOsDirisusedtohelpcreateeitheraWindows95orWindowsNTspecificpath.
rem
setVcOsDir=WIN95
if"%OS%"=="Windows_NT"setVcOsDir=WINNT

rem
echoSettingenvironmentforusingMicrosoftVisualC++tools.
rem

if"%OS%"=="Windows_NT"setPATH=%MSDevDir%BIN;%MSVCDir%BIN;%VSCommonDir%TOOLS%VcOsDir%;%VSCommonDir%TOOLS;%MSVCDir%DEBUG;%VSCommonDir%OSSYSTEM;%PATH%
if"%OS%"==""setPATH="%MSDevDir%BIN";"%MSVCDir%BIN";"%VSCommonDir%TOOLS%VcOsDir%";"%VSCommonDir%TOOLS";"%windir%SYSTEM";"%PATH%";%VSCommonDir%OSSYSTEM
setINCLUDE=%MSVCDir%ATLINCLUDE;%MSVCDir%INCLUDE;%MSVCDir%MFCINCLUDE;%INCLUDE%
setLIB=%MSVCDir%LIB;%MSVCDir%MFCLIB;%LIB%

remsetVcOsDir=
rem
setVSCommonDir=

remmodifiedbyxionghe,antpath,classpathetc.
setpath=%path%;d:/jakarta-ant/bin
setJAGUAR_JDK13=d:/sharedjdk1.3.1_11
setJAGUAR_JDK14=d:/sharedjdk1.4.2_06
setJAGUAR_JDK15=d:/sharedjdk1.5.0_01
setJAVA_HOME=%JAGUAR_JDK14%
setPATH=%JAVA_HOME%bin;%JAVA_HOME%/jre/bin;%PATH%
setOLD_CLASSPATH=%CLASSPATH%
setCLASSPATH=.;%JAVA_HOME%/lib/dt.jar;%JAVA_HOME%/lib/tools.jar;%JAVA_HOME%/jre/lib/rt.jar
setCLASSPATH=%CLASSPATH%;%OLD_CLASSPATH%

setINCLUDE=%JAVA_HOME%/include;%JAVA_HOME%/include/win32;%INCLUDE%

startcmd
我们在Run窗口里直接运行D:/msdev/VC98/Bin/vcvars32,就会新启一个带有C++以及Java JNI相关环境变量的cmd窗口。进入到刚才的class目录,运行:
cl -MD -LD helloworldimp.cpp -Fehelloworld.dll
动态库即可build成功。
于是我们可以运行java jnitest.HelloWorld,得到结果了。
稍复杂一点的例子,改变本地函数中的参数值。

三、复杂一点的例子:

的fs
我们看看下边的这个类:
publicclassPrompt...{
publicPrompt()...{
}

privatenativeStringgetLine(Stringprompt);
static...{
System.loadLibrary(
"helloworld");
}

publicstaticvoidmain(String[]args)...{
Promptprompt
=newPrompt();
Stringinput
=prompt.getLine("Typealine:");
System.out.println(
"usertyped:"+input);
}

}
Prompt类,就是想调用C代码中的用户输入,然后把输入的东西回显出来,就这么简单,但是返回值是用户输入的串,不是参数里的prompt值。加载的动态库依然借用前边的helloworld.dll,这里不带包名,以与前例区分。
使用javah生成的头文件Prompt.h如下:
/**//*DONOTEDITTHISFILE-itismachinegenerated*/
#include
<jni.h>
/**//*HeaderforclassPrompt*/

#ifndef_Included_Prompt
#define_Included_Prompt
#ifdef__cplusplus
extern"C"...{
#endif
/**//*
*Class:Prompt
*Method:getLine
*Signature:(Ljava/lang/String;)Ljava/lang/String;
*/

JNIEXPORTjstringJNICALLJava_Prompt_getLine
(JNIEnv
*,jobject,jstring);

#ifdef__cplusplus
}

#endif
#endif
下边是完整的实现,将前例和本例的合到了一起(helloworldimp.cpp)。
#include<jni.h>
#include
"jnitest_HelloWorld.h"
#include
"Prompt.h"
#include
<stdio.h>

JNIEXPORTjstringJNICALLJava_jnitest_HelloWorld_echoString
(JNIEnv
*env,jobjectobj,jstringsz)
...{
returnsz;
}



/**//**
*PromptDllfunctionentry
*/

JNIEXPORTjstringJNICALLJava_Prompt_getLine
(JNIEnv
*env,jobjectobj,jstringprompt)
...{
charbuf[128];
constchar*str;//charisjustthejbyte
str=(env)->GetStringUTFChars(prompt,NULL);
if(str==NULL)...{
returnNULL;/**//*OutOfMemoryErroralreadythrown*/
}

printf(
"%s",str);
(env)
->ReleaseStringUTFChars(prompt,str);
/**//*Weassumeherethattheuserdoesnottypemorethan
*127characters
*/

scanf(
"%s",buf);
return(env)->NewStringUTF(buf);
}

运行java -Djava.library.path=D:/msdev/MyProjects/helloworld Prompt,结果如下:
Type a line: fjkal
user typed: fjkal
注意,这里需要指定jvm的java.library.path值,表示load动态库时的搜索路径,或者你把生成的动态库拷贝到PATH路径中的任一目录里也可以,但不推荐这么做。
还要注意一点的是C++代码和C代码里env的调用形式不太一样。
C++:
(env)->ReleaseStringUTFChars(prompt,str);
而C:
(env*)->ReleaseStringUTFChars(env, prompt,str);
前边的实现里,必须作出jstring类型到char*的转换,并且适时的要释放内存,否则会出现内存泄漏。
这是一些比较简单的例子。后边会有适当的篇幅介绍jni以及jvm中一些比较复杂的应用。
分享到:
评论

相关推荐

    Java programming with JNI.pdf

    Java programming with JNI.pdf Java programming with JNI.pdf

    Advanced.Java.Programming.0199455503

    Advanced Java Programming is a textbook specially designed for undergraduate and postgraduate students of Computer Science, Information Technology, and Computer Applications (BE/BTech/BCA/ME/M.Tech/...

    java jni 教程 资料

    This chapter introduces the Java Native Interface (JNI). The JNI is a native programming interface. It allows Java code that runs inside a Java Virtual Machine (VM) to interoperate with applications ...

    Java programming with JNI

    This tutorial deals with the two most common applications of JNI: calling C/C++ code from ...of the Java Native Interface and some of the more advanced programming challenges that can arise.

    Java_programming_with_JNI

    jni开发手册,c调用java,java调用c Java_programming_with_JNI

    JavaSE-6.0-英文手册(2008/11/30_FullUpdate)

    An example-filled guide to the Java programming language and core APIs. Java Technology Home Page Training for the Java programming language Directory of various training resources. Demonstration ...

    Best practices for using JNI

    Best practices for using the Java Native Interface Techniques and tools for averting the 10 most common JNI programming mistakes.

    Java2游戏编程.pdf

    原名: Java 2 Game Programming 作者: Thomas Petchel译者: 晏利斌 孙淑敏 邵荣 资源格式: PDF 版本: 扫描版 出版社: 清华大学出版社书号: 7302112932发行时间: 2005年08月 地区: 大陆 语言: 简体中文 简介: ...

    J/Invoke 2010 jinvoke jni 天涯浪子

    Unlike error-prone JNI programming that is hard to use and deploy, J/Invoke lets you access native libraries by simply declaring native methods, and calling them from pure Java. Java programmers can ...

    Advanced Programming for the Java 2 Platform.chm

    Advanced Programming for the Java 2 Platform.chm 里边有很多不怎么为人所知的东西,时常参考,还是蛮有好处的 Chapter 1: Matching Project Requirements with Technology &lt;br&gt;Project Requirements ...

    java7帮助文档

    Java Virtual Machine Support for Non-Java Languages: Java SE 7 introduces a new JVM instruction that simplifies the implementation of dynamically typed programming languages on the JVM. Garbage-First...

    台湾高焕堂Android讲义

    1.高焕堂讲解 Intent-based Programming.doc 2.高焕堂讲解 ContentProvider范例.doc 3.实际演练Android仿真器之操作.doc 4.Android与Cross Compiler之关系.doc 5.认识Android Application.doc 7.Android里的类别继承...

    《C++ for Java Programmers》高清完整英文PDF版

    Written for the moderately experienced Java programmer, this book builds on readers¿ existing knowledge of object-oriented programming and covers all important aspects of Standard C++—emphasizing ...

    Java教程补充材料

    1 Java Characteristics 2 Discussion on Operator and Operand Evaluations 3 The "&" and "|" Operators 4 Bit-wise Operations 5 Statement Labels with break and continue 6 Enumerated Types 7 ...

    Android Application Programming with OpenCV 3(PACKT,2015)

    Android Application Programming with OpenCV 3 is a practical, hands-on guide to computer vision and mobile app development. It shows how to capture, manipulate, and analyze images while building an ...

    Core Java Volume II Advanced Features__10th edition

    •Elegantly overcome date/time programming complexities with the new java.time API •Write internationalized programs with localized dates/times, numbers, text, and GUIs •Process code with the ...

    高焕堂关于Android讲义

    1.高焕堂讲解 Intent-based Programming 2.高焕堂讲解 ContentProvider范例 3.实际演练Android仿真器之操作 4.Android与Cross Compiler之关系 5.认识Android Application 6. 7.Android里的类别继承及对象组合 8...

    Asynchronous Android Programming

    Use the JNI interface to execute concurrent work on native layer Pull and push data from your network servers using the Google GCM platform Create and compose tasks with RxJava to execute complex ...

    corejava的学习笔记

    JAVAC的帮助,输入[sd0807@localhost ~]$ javac 编译:javac ***.java ... load Java programming language agent, see java.lang.instrument -splash:&lt;imagepath&gt; show splash screen with specified image

Global site tag (gtag.js) - Google Analytics