在c/c++中调用Java方法
2017-05-11 14:42
288 查看
JNI就是Java Native Interface, 即可以实现Java调用本地库, 也可以实现C/C++调用Java代码, 从而实现了两种语言的互通, 可以让我们更加灵活的使用.
通过使用JNI可以从一个侧面了解Java内部的一些实现.
本文使用的环境是
64位的win7系统
JDK 1.6.0u30 (32位)
C/C++编译器是 Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86 (VC 6.0的, 其他版本的也可以编译通过, 测试过vs2010)
本文使用到的一些功能:
创建虚拟机
寻找class对象, 创建对象
调用静态方法和成员方法
获取成员属性, 修改成员属性
C/C++调用Java代码的一般步骤:
编写Java代码, 并编译
编写C/C++代码
配置lib进行编译, 配置PATH添加相应的dll或so并运行
编写Java代码并编译
这段代码非常简单, 有个静态方法和成员方法, 一个public的成员变量
?
由于没有定义构造函数, 所以会有一个默认的构造函数.
运行下面的命令编译
?
可以在当前目录下看到Sample2.class文件, 编译成功, 第一步完成了, So easy!
可以查看Sample2类中的签名
?
结果如下
?
关于签名的含义, 请参看使用JNI进行Java与C/C++语言混合编程(1)--在Java中调用C/C++本地库.
编写C/C++代码调用Java代码
先贴代码吧
?
这段代码大概做了这几件事
创建虚拟机JVM, 在程序结束的时候销毁虚拟机JVM
寻找class对象
创建class对象的实例
调用方法和修改属性
虚拟的创建
与之相关的有这样几个变量
JavaVMOption options[1]; JNIEnv *env; JavaVM *jvm; JavaVMInitArgs vm_args;
JavaVM就是我们需要创建的虚拟机实例
JavaVMOption相当于在命令行里传入的参数
JNIEnv在Java调用C/C++中每个方法都会有的一个参数, 拥有一个JNI的环境
JavaVMInitArgs就是虚拟机创建的初始化参数, 这个参数里面会包含JavaVMOption
下面就是创建虚拟机
?
"-Djava.class.path=."看着眼熟吧, 这个就是传入当前路径, 作为JVM寻找class的用户自定义路径, 我们的Sample2.class就在当前路径(当然也可以不在当前路径, 你可以随便修改).
vm_args.version是Java的版本, 这个应该是为了兼容以前的JDK, 可以使用旧版的JDK, 这个宏定义是在jni.h中, 有以下四种
?
vm_args.nOptions的含义是, 你传入的options有多长, 我们这里就一个, 所以是1.
vm_args.options = options把JavaVMOption传给JavaVMInitArgs里面去.
然后就是启动虚拟机了status = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args).
可以通过这个返回值status , 知道虚拟机是否启动成功
?
寻找class对象, 并实例化
JVM在Java中都是自己启动的, 在C/C++中只能自己来启动了, 启动完之后的事情就和在Java中一样了, 不过要使用C/C++的语法.
获取class对象比较简单, FindClass(env, className).
?
在Java中的类名格式是java.lang.String, 但是className的格式有点不同, 不是使用'.'作为分割, 而是'/', 即java/lang/String.
我们知道Java中构造函数有两种, 一种是默认的没有参数的, 一种是自定义的带有参数的. 对应的在C/C++中, 有两种调用构造函数的方法.
调用默认构造函数
?
构造函数也是方法, 类似调用方法的方式.
?
调用方法和修改属性
关于方法和属性是有两个ID与之对应, 这两个ID用来标识方法和属性.
?
方法分为静态和非静态的, 所以对应的有
?
上面两个方法是同名的, 都叫sayHello, 但是签名不同, 所以可以区分两个方法.
JNI的函数都是有一定规律的, Static就表示是静态, 没有表示非静态.
方法的调用如下
?
我们可以看到静态方法是只需要class对象, 不需要实例的, 而非静态方法需要使用我们之前实例化的对象.
属性也有静态和非静态, 示例中只有非静态的.
获取属性ID
?
修改属性的值
?
关于jstring的说明
java的String都是使用了unicode, 是双字节的字符, 而C/C++中使用的单字节的字符.
从C转换为java的字符, 使用NewStringUTF方法
?
从java转换为C的字符, 使用GetStringUTFChars
?
编译和运行
编译需要头文件, 头文件在这两个目录中%JAVA_HOME%\include和%JAVA_HOME%\include\win32, 第一个是与平台无关的, 第二个是与平台有关的, 由于笔者的系统是windows, 所以是win32.
编译的时候还要一个lib文件, 是对虚拟机的支持, 保证编译通过.
?
我们可以看到在当前目录下Sample2.exe, 运行的时候需要jvm.dll(不要将其复制到当前目录下, 这样不可以运行, 会导致jvm创建失败)
?
jvm.dll在%JAVA_HOME%\jre\bin\client\目录下, 所以我把这个目录加入到PATH中, 然后就可以运行
?
关于C++的说明
本示例的C++版本, 请自行下载后面的源代码来查看, 区别不是很大.
主要是JNIEnv和JavaVM两个对象, 在C中是结构体, 是函数指针的集合, 在C++中结构体拥有类的能力, 使用起来更为简便, 与Java之间的差异更小一些.
结语
本文介绍了一个简单的例子, 分析了其中的一些代码, 笔者希望通过这篇文章让大家对JNI的了解更加深入一些.
水平有限, 错漏在所难免, 欢迎指正!
源代码下载: c调用java.zip
使用方法: 参照里面的build&run.bat, 使用了%JAVA_HOME%环境变量.
注意:
动态链接库和JDK都有32位和64位的区别, 使用64位系统的朋友, 要注意这个问题, 可能导致运行或编译错误.
还要注意区分C和C++代码, 在JNI中两种代码有一定的区别, 主要是env和jvm两个地方.
作者:icejoywoo
出处:http://www.cnblogs.com/icejoywoo/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利. 短网址: http://goo.gl/ZiZCi
通过使用JNI可以从一个侧面了解Java内部的一些实现.
本文使用的环境是
64位的win7系统
JDK 1.6.0u30 (32位)
C/C++编译器是 Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86 (VC 6.0的, 其他版本的也可以编译通过, 测试过vs2010)
本文使用到的一些功能:
创建虚拟机
寻找class对象, 创建对象
调用静态方法和成员方法
获取成员属性, 修改成员属性
C/C++调用Java代码的一般步骤:
编写Java代码, 并编译
编写C/C++代码
配置lib进行编译, 配置PATH添加相应的dll或so并运行
编写Java代码并编译
这段代码非常简单, 有个静态方法和成员方法, 一个public的成员变量
?
运行下面的命令编译
?
可以查看Sample2类中的签名
?
?
编写C/C++代码调用Java代码
先贴代码吧
?
创建虚拟机JVM, 在程序结束的时候销毁虚拟机JVM
寻找class对象
创建class对象的实例
调用方法和修改属性
虚拟的创建
与之相关的有这样几个变量
JavaVMOption options[1]; JNIEnv *env; JavaVM *jvm; JavaVMInitArgs vm_args;
JavaVM就是我们需要创建的虚拟机实例
JavaVMOption相当于在命令行里传入的参数
JNIEnv在Java调用C/C++中每个方法都会有的一个参数, 拥有一个JNI的环境
JavaVMInitArgs就是虚拟机创建的初始化参数, 这个参数里面会包含JavaVMOption
下面就是创建虚拟机
?
vm_args.version是Java的版本, 这个应该是为了兼容以前的JDK, 可以使用旧版的JDK, 这个宏定义是在jni.h中, 有以下四种
?
vm_args.options = options把JavaVMOption传给JavaVMInitArgs里面去.
然后就是启动虚拟机了status = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args).
可以通过这个返回值status , 知道虚拟机是否启动成功
?
JVM在Java中都是自己启动的, 在C/C++中只能自己来启动了, 启动完之后的事情就和在Java中一样了, 不过要使用C/C++的语法.
获取class对象比较简单, FindClass(env, className).
?
我们知道Java中构造函数有两种, 一种是默认的没有参数的, 一种是自定义的带有参数的. 对应的在C/C++中, 有两种调用构造函数的方法.
调用默认构造函数
?
?
关于方法和属性是有两个ID与之对应, 这两个ID用来标识方法和属性.
?
?
JNI的函数都是有一定规律的, Static就表示是静态, 没有表示非静态.
方法的调用如下
?
属性也有静态和非静态, 示例中只有非静态的.
获取属性ID
?
?
java的String都是使用了unicode, 是双字节的字符, 而C/C++中使用的单字节的字符.
从C转换为java的字符, 使用NewStringUTF方法
?
?
编译需要头文件, 头文件在这两个目录中%JAVA_HOME%\include和%JAVA_HOME%\include\win32, 第一个是与平台无关的, 第二个是与平台有关的, 由于笔者的系统是windows, 所以是win32.
编译的时候还要一个lib文件, 是对虚拟机的支持, 保证编译通过.
?
?
?
本示例的C++版本, 请自行下载后面的源代码来查看, 区别不是很大.
主要是JNIEnv和JavaVM两个对象, 在C中是结构体, 是函数指针的集合, 在C++中结构体拥有类的能力, 使用起来更为简便, 与Java之间的差异更小一些.
结语
本文介绍了一个简单的例子, 分析了其中的一些代码, 笔者希望通过这篇文章让大家对JNI的了解更加深入一些.
水平有限, 错漏在所难免, 欢迎指正!
源代码下载: c调用java.zip
使用方法: 参照里面的build&run.bat, 使用了%JAVA_HOME%环境变量.
注意:
动态链接库和JDK都有32位和64位的区别, 使用64位系统的朋友, 要注意这个问题, 可能导致运行或编译错误.
还要注意区分C和C++代码, 在JNI中两种代码有一定的区别, 主要是env和jvm两个地方.
作者:icejoywoo
出处:http://www.cnblogs.com/icejoywoo/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利. 短网址: http://goo.gl/ZiZCi
相关文章推荐
- C++JAVA程序调用weka聚类算法的方法
- Android-NDK开发之基础--Android JNI实例代码(一)-- 在JNI中执行Java方法--C/C++调用Java
- c++调用java时得到java签名的方法javap -s -p <classname>
- C++调用Java又一方法
- C++调用JAVA方法详解
- C++调用JAVA方法详解(转)
- JNI:Java调用C/C++-传递空值(null)的处理方法
- C++中调用Java的方法
- java程序调用c++的实现方法
- C++调用JAVA方法详解
- Android-NDK开发之基础--Android JNI实例代码(一)-- 在JNI中执行Java方法--C/C++调用Java
- Android-NDK开发之基础--Android JNI实例代码(一)-- 在JNI中执行Java方法--C/C++调用Java
- JAVA如何调用C/C++方法
- Java调用C++和C++调用Java的方法
- C++/JAVA程序调用weka聚类算法的方法 推荐
- 3Java程序JNI调用C++之修改属性调用方法
- 如何在C/C++中调用Java的方法
- C++调用JAVA方法详解_____转载自http://public0821.iteye.com/blog/423941
- C++ 代码创建虚拟机调用java方法
- Android 中Java 和C/C++的相互调用方法