java JNI 的实现-又进一步加深对JVM实现的理解

目录  

  概述

    主要优点

    主要缺点

  JNI实现的简单例子

    开发工具

    简略步骤

      1,在eclipse的 ‘java类‘ 中声明一个 ‘native方法‘;

      2,使用 ‘javah‘ 命令生成包含‘native方法‘ 定义的 ‘C/C++头文件‘;

      3,使用 ‘C/C++‘实现以上生成的 ‘C/C++头文件‘ 中的方法;

      4,将实现的文件编译‘.dll‘动态链接库;

      5,在eclipse中将 ‘.dll动态链接库所在路径‘ 加入eclipse中的 ‘classpath‘;

      6,在eclipse中的java类中加载.dll调用native方法.

    具体步骤

      1.

      2.

      3.

      4.

      5.

      6.



概述

  其实细心点的程序员应该注意到,java的源码中,方法的实现,要么是具体实现,要么是定义为native.而定义为native的方法则交给诸如C之类等语言,在具体的操作系统上去实现.我们知道java是通过JVM运行的,而JVM多是通过C和汇编实现的.我们可以猜测,具体就是通过强大的sun提供的JNI这个桥梁去实现.

  我们也因此知道,为什么每一种操作系统,对应不同的JVM,其实就是JNI的具体实现是非跨平台引起的.

  关于JNI调用 的一些过程,大体上还算理解了点.

  主要优点:

    1. java语言调用其他语言(如,C/C++)的实现.这个有时确实算是需要的,比如java需要调用一种方法(这个方法的算法很难,但是已经由非java语言写的,而且你很急,如果要用java实现,会花很多开发成本).
    2. 高性能,这个我一开始不是很明白,其实JNI的实现,能使用旧的库,使用一些依赖于机器语言交换,这自然就提高了性能了.

  主要缺点:

    1. 从上面的第2点,暴漏了很明显的缺点,我们在使用JNI进行与操作系统等直接交互,或很依赖机器或硬件的时,自然可移植就丧失了.所以JNIj是ava的一部分,但是要慎用,比较,java是因其跨平台而出名的.也就是说,如果这个程序(基于JNI的)需要跨平台,则native方法声明的具有实现,需要重新修改(这是一个开发成本的开销).
    2. 使用JNI还有一个优点,就是,java是强类型语言,是一种编译型语言,而C/C++不是,所以在开发时需要很小心,毕竟C/C++这类语言之间操作内存,是非安全的.

JNI实现的简单例子

  下面说明一下,如何使用一个简单的JNI程序,好进一步理解JNI:

  开发工具:

    1,JDK v1.7.0_71(x64);

    2,Eclipse Java EE IDE for Web Developers(Indigo Release),即eclipse v3.7.0;

    3,Visual Studio 2013 express(x86);

    4,我的操作系统是win7旗舰版SP1(x64).

  简略步骤:

    1,在eclipse的 ‘java类‘ 中声明一个 ‘native方法‘;

    2,使用 ‘javah‘ 命令生成包含‘native方法‘ 定义的 ‘C/C++头文件‘;

    3,使用 ‘C/C++‘实现以上生成的 ‘C/C++头文件‘ 中的方法;

    4,将实现的文件编译‘.dll‘动态链接库;

    5,在eclipse中将 ‘.dll动态链接库所在路径‘ 加入eclipse中的 ‘classpath‘;

    6,在eclipse中的java类中加载.dll调用native方法.

  具体步骤:

    1,在eclipse中新建一个名为 ‘SayHello‘ 的Java Project,添加一个全名为‘juk.demo.SayHello‘的类,代码为:

 1 package juk.demo;
 2
 3 public class SayHello {
 4
 5     public  native void SayHello();
 6
 7     public static void main(String[] args) {
 8
 9     }
10
11 }

    2,通过 ‘cmd‘ 打开命令行窗口,进入‘SayHello‘根目录下的‘bin‘目录,使用 ‘javah juk.demo.SayHello‘命令生成包含‘native方法‘ 定义的 ‘C/C++头文件‘;

    3,A,打开VS2013,通过‘File->New Project‘打开‘New Project‘对话框,选择左侧的‘Templates/Visual C++/Win32‘,然后选择‘Win32 Project‘,输入名为‘CppSay‘的项目名,选择合适的路径,确定.B,在 ‘Solution Explore‘视图下,在‘CppSay‘项目上右键,选择‘Open Folder in File Explore‘,并将以上第一步生成的 ‘C/C++头文件‘放入与 ‘CppSay.vcxproj‘ 同级的目录下.同理,将JDK安装目录下的 ‘include\jni.h‘ 和 ‘include\win32\jni_md.h‘(例如‘H:\Program Files\Java\jdk1.7.0_71\include\jni.h‘ 和 ‘H:\Program Files\Java\jdk1.7.0_71\include\win32‘),加入同样的目录中.C,在‘Solution Explore‘视图的 ‘Header Files‘ 上右键,选择"Add->Existing Item"引入刚添加的3个 .h头文件.在‘Solution Explore‘视图的 ‘Source Files‘上添加一个 ‘.cpp文件,实现java定义的native方法(通过机器生成的函数原型),代码为:

1 #include <iostream>
2 #include "juk_demo_SayHello.h"
3 using namespace std;
4
5 //(函数原型在"juk_demo_SayHello.h"中)在C/C++中实现通过javah 产生的头文件的函数(或者说在C/C++中实现java定义的native方法).
6 JNIEXPORT void JNICALL Java_juk_demo_SayHello_SayHello
7   (JNIEnv * env, jobject obj) {
8     cout<<"hello, java native interface"<<endl;
9 }

    4,将VS2013 ‘Standard‘工具条中的‘Solution Platform‘修改为‘x64‘(因为我的JDK是x64),不然在java中加载dll的时候会报错:Can‘t load IA 32-bit .dll on a AMD 64-bit platform,然后编译整个项目,会在‘解决方案‘的 ‘x64‘目录中的Debug目录下,产生‘CppSay.dll‘动态链接库(注意是解决方案下的Debug,而不是项目下的Debug),目录如‘C:\Users\Administrator\Documents\visual studio 2012\Projects\CppSay\x64\Debug‘

    5,在eclipse的‘SayHello‘项目下的 ‘JRE System Library‘上右键,选择 ‘Build Path‘->‘Config Build Path‘,选择 ‘Java Build Path‘下的‘JRE System Library‘中的 ‘Native library location‘,点击右侧的‘Edit‘,将上面第4步产生‘CppSay.dll‘的目录选中,即完成classpath的配置.

    6,在第1步中的Java类中,定义一个静态代码块,使用:

System.loadLibrary("CppSay")

加载动态链接库(也可以不通过静态代码块),注意的是,名称不能包含‘.dll‘,否则会报错: java.lang.UnsatisfiedLinkError: no CppSay.dll in java.library.path,运行eclipse的‘SayHello‘项目,会在控制台上输出: ‘hello, java native interface‘.

JNI的简单使用就是这样了.  

        

时间: 2024-10-06 16:00:12

java JNI 的实现-又进一步加深对JVM实现的理解的相关文章

java JNI 的实现(2)-java和C/C++的相互调用.

目录 概述 一,java代码 二,稍微注意通过javah生成的'C/C++'.h头文件和源java代码的关系 三,在C/C++中实现java的native方法(完整C/C++) 1,修改age,即Java_juk_demo_JSay_changeAge方法 2,调用java中的'javaStatic'方法,和上面C/C+实现方法相似 3,最后测试 概述 从第一篇java JNI 的实现(1)-又进一步加深对JVM实现的理解对JNI有了大致的理解之后,并知道JNI中java如何调用C/C++等,这

学JAVA第十八天,接口与抽象类进一步加深

昨天老师讲了建网站,还要交钱买东西的,所以就没写,今天讲了接口与抽象类进一步加深 上完今天的课后,我才知道一个接口可以有多个实现类,一个实现类可以同时接多个接口. 现在就用代码来解释吧!!! 举例用人(People)来写 先创建一个父类: package pkg34;//这是一个 [人] 类 public class People{ public void Having (){ } //这是表明人拥有的基本方法 public void Sleep(){ } } 然后 创建接口1 下边每一个接口的

JNI/NDK开发指南(二)——JVM查找java native方法的规则

通过第一篇文章,大家明白了调用native方法之前,首先要调用System.loadLibrary接口加载一个实现了native方法的动态库才能正常访问,否则就会抛出java.lang.UnsatisfiedLinkError异常,找不到XX方法的提示.现在我们想想,在Java中调用某个native方法时,JVM是通过什么方式,能正确的找到动态库中C/C++实现的那个native函数呢? JVM查找native方法有两种方式: 1> 按照JNI规范的命名规则 2> 调用JNI提供的Regist

关于java jni编译javac javah的问题

这篇文章是在安卓教程网http://android.662p.com那边分享过来的,文章说得还不错的,希望能够帮到大家的学习. javac  编译class文件命令,需要注意的是当类B中import类A时,在编译B时要包含A的路径,如 project  src  com.jl.test  A.java com.jl.test2 B.java B中importA,在编译B时应该  : javac  -cp ~/project/src  B.java       (-cp :classpath简称,

编程基础知识——Java JNI开发流程(2)

android中使用jni调用本地C++库 android平台上的本地库文件后缀 .so.类似windows上的dll文件. 要在android上使用jni,首先需要下载android ndk. 操作步骤,正常建立android工程,然后在android工程那里右键,属性,选择Android Tools -> Add Native Support.就可以为android工程增加本地库支持. 添加支持后的android工程,会增加jni目录,C++代码就写在这个目录里. 新建一个类,并且使用nat

Android(Java):jni源代码

public void onCreate(Bundle savedInstanceState)    {        super.onCreate(savedInstanceState);        Button btn = new Button(this);        btn.setText("测试ndk");        btn.setOnClickListener(new ButtonOnClickListener());        setContentView(

java JNI 调试出现的错误

java JNI 调试出现的错误 ERROR: JDWP Unable to get JNI 1.2 environment, jvm->GetEnv() return code = -2JDWP exit error AGENT_ERROR_NO_JNI_ENV(183): [../../../src/share/back/util.c:820] 请在代码最后加入以下语句:System.exit(0)即可(在main函数结束时,添加system.exit(0):), 注意,只需要在这种情况下加

JAVA JNI学习

JAVA JNI   JNI是Java Native Interface的缩写,中文为JAVA本地调用.从Java1.1开始,Java Native Interface(JNI)标准成为java平台的一部分,它允许Java代码和其他语言写的代码进行交互.JNI一开始是为了本地已编译语言,尤其是C和C++而设计的,但是它并不妨碍你使用其他语言,只要调用约定受支持就可以了. 设计目的 标准的java类库可能不支持你的程序所需的特性. JNI 或许你已经有了一个用其他语言写成的库或程序,而你希望在ja

Mac下Java JNI (java native interface)调C

1.编写带有native声明的方法的Java类 2.使用javac命令编译编写的Java类 3.使用java -jni className 来生成后缀名为.h的头文件 4.使用其他语言(C.C++)实现本地方法 5.将本地方法编写的文件生成动态链接库 一代码:(不要带包路径) /** * native-0study * * @author xuedui.zhao * @create 2018-04-23 */public class HelloWorld { public native void