JNI之C++调用Java类
——java.lang.String
为什么要用C++调用Java类?很难回答,写着文章只是觉得JNI很有意思。于是开始编写一段使用VC++在Windows系统里调用java的String类,在C++里调用String类内的一些方法。
JNI已经被开发了很多年,而在我2年多的Java编程时间里从来没有接触过。直到最近研究JVM实现原理才注意到JNI。 JNI既Java Native Interface,Native这个词我见过我认为最恰当的翻译就是原生。原生的意思就是来自系统自己的,原汁原味的东西,例如Win32 API。Java类需要在虚拟机上运行,也就不是原生的,同样.NET Framework也不是原生的。JNI也就是Java原生接口。关于JNI的规范,以及为什么要使用它,它能做些什么,都在http://java.sun.com/j2se/1.4.2/docs/guide/jni/spec/jniTOC.html里记述着。
JNI是规范,它规定了虚拟机的接口,而把具体的实现留给开发者。
JVM的实现不是唯一的,目前存在很多种Java虚拟机,Sun Hotspot,IBM JDK,还有HP的,Kaffe等等。最流行的就是Sun的Hotspot,最复杂的就是IBM JDK,这是IBM的一贯作风。本文不讨论JVM的实现,只关注JNI。如果您安装了Sun的JDK,您就能在[JAVA_HOME]\include目录下找到jni.h。这个头文件就是虚拟机的唯一接口,你可以调用它声明的函数创建一个JVM。
在说明C++调用Java类之前,我想先演示一下如果编写Java Native Method。
1.编写带有Native方法的Java类
package org.colimas.jni.test;
public class JniTest {
static { System.loadLibrary("JniTestImpl"); } //JVM调用JniTestImpl.dll
public JniTest(){
}
//原生方法
public native void print(String str);
/**
* @param args
*/
public static void main(String[] args) {
JniTest test=new JniTest();
test.print("hello JVM"); //调用原生方法
}
}
2.使用javah生成c语言头文件。
javah -jni org.colimas.jni.test.JniTest
目录里多了一个org_colimas_jni_test_JniTest.h文件,打开文件,内容如下:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class org_colimas_jni_test_JniTest */
#ifndef _Included_org_colimas_jni_test_JniTest
#define _Included_org_colimas_jni_test_JniTest
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: org_colimas_jni_test_JniTest
* Method: print
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_org_colimas_jni_test_JniTest_print
(JNIEnv *, jobject, jstring);
#ifdef __cplusplus
}
#endif
#endif
其中的Java_org_colimas_jni_test_JniTest_print就是JniTest类里面的print原生方法的C语言声明。
3.编写C代码实现原生方法print
#include <jni.h>
#include "org_colimas_jni_test_JniTest.h" //javah生成的头文件
#include <stdio.h>
JNIEXPORT void JNICALL Java_org_colimas_jni_test_JniTest_print
(JNIEnv *env, jobject object,jstring str)
{
//获得字符串
const char * txt=(*env)->GetStringUTFChars(env,str,0);
printf("%s\n",txt); //打印到控制台
return;
}
参数JNIEnv *env,是JNI里最重要的变量。Java.exe创建JVM,之后JVM生成一个env,该env相当于JVM内的Session,可以完成创建Java对象,调用类方法,获得类的属性等等。
在这里env将方法的参数Str从JNI的jstring类型转换为常数char数组。
4.编译
cl /Ic:\j2sdk<chsdate w:st="on" isrocdate="False" islunardate="False" day="30" month="12" year="1899">1.4.2</chsdate>_10\include /Ic:\j2sdk1.4.2_10\include\win32 /c JniTestImpl.c
5.连接为DLL
link /dll JniTestImpl.obj
6.设置PATH
set PATH=C:\MyProject\Colimas\CD\JNI\MyJNI;%PATH%
7.运行
java org.colimas.jni.test.JniTest
返回结果
hello JVM
结束
以上是实现Java原生方法的开发过程,下面进入正题,使用C++调用Java的java.lang.String类。
1. Object类出创建JVM。
使用Java类之前必须要创建JVM环境。JDK由java.exe来完成。本文有Object类的静态方法BeginJVM来创建,用EndJVM来关闭。
创建JVM之后会在创建2个变量,分别是JNIEnv* env和JavaVM* jvm,JNIEnv上文已经说明,JavaVM,顾名思义,代表Java虚拟机,用它来关闭JVM。
Object类的头文件
#include "jni.h"
class Object
{
public:
static bool BeginJVM();
static bool EndJVM();
Object();
virtual ~Object();
protected:
static JNIEnv* env;
static JavaVM* jvm;
};
object.cpp代码
#include "stdafx.h"
#include "JavaClasses.h"
#include "Object.h"
Object::Object()
{}
Object::~Object()
{}
JNIEnv* Object::env=NULL;
JavaVM* Object::jvm=NULL;
//创建JVM
bool Object::BeginJVM()
{
JavaVMOption options[3];
JavaVMInitArgs vm_args;
//各种参数
options[0].optionString="-Xmx<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="128" unitname="m">128m</chmetcnv>";
options[1].optionString="-Verbose:gc";
options[2].optionString="-Djava.class.path=.";
vm_args.version=JNI_VERSION_1_2;
vm_args.options=options;
vm_args.nOptions=3;
//创建JVM,获得jvm和env
int res = JNI_CreateJavaVM(&jvm,(void **)&env, &vm_args);
return true;
}
bool Object::EndJVM()
{
//关闭JVM
jvm->DestroyJavaVM();
return true;
}
2. C++的String类调用java.lang.String类方法
编写C++版的String类,调用java String类方法。调用的方法如下:
String replaceAll(String regex, String replacement);
boolean endsWith(String str);
int indexOf(String str);
int compareTo(String anotherString);
char charAt(int i);
String的头文件:
class String :public Object
{
public:
//与要调用的Java方法名一致。
const char * replaceAll(char *regex,char *replacement);
bool endsWith(char * str);
int indexOf(char * str);
int compareTo(char *anotherString);
char charAt(int i);
String(char *str);
virtual ~String();
};
实现:
#include "stdafx.h"
#include "String.h"
#include "jni.h"
using namespace std;
jclass clazz; //全局变量,用来传递class
jobject object; //全局变量,用来传递object
String::String(char *str)
{
jstring jstr;
if (Object::env ==NULL)
{
cout << "JVM is not created" << endl;
exit(-1);
}
//获得java.lang.String类
clazz=Object::env->FindClass("java/lang/String");
if (clazz ==0 ){
cout << "Class is not found" << endl;
exit(-1);
}
//获得String(String str)构造体
jmethodID mid= Object::env->GetMethodID(clazz,"<init>", "(Ljava/lang/String;)V");
if (mid==0){
cerr<< "GetMethodID Error for class" << endl;
分享到:
相关推荐
jni_c++调用java中的方法 文档中包含(c++与js互相调用的实现)
C++调用java代码验证用户和权限的JNI实现 JAVA代码说明: C++代码说明: 头文件包括三个stdafx.h、jni.h、jni_md.h stdafx.h:vc2005自动生成的,在这个文件中要加入jni相关的头文件如下 jni.h:jdk中自带的...
II. java c/cpp互相调用实例(姊妹篇之一)——java调用c/cpp 4 一 先制作一个系统中有的DLL文件(cpp给出的sdk接口) 4 二 JNI 7 1、 编写java文件 7 2、 生成.h头文件 8 3、 用c/cpp实现这个头文件 9 三 测试 10 ...
c++通过jni调用java类. jdk1.6下通过测试
visual studio 2019下C++通过JNI调用JAVA代码
Android Studio项目,此Demo实现Java调用C++函数,然后C++函数回调Java方法、纯C++直接调用Java方法,此为github地址链接
jni调用c++ delphi中的dll.
Chap5:使用JNI技术实现java程序调用第三方dll(c/c++)文件的功能... 47 Chap9:如何编写jni方法(转载)... 55 1、实例一:在jni中调用标准c中自带的函数printf(): 57 2、实例二、调用c 语言用户定义的函数... 58 ...
Android Studio3.0开发JNI流程,C++调用Java以及Java调用C++,C++/Java互相调用一个简单案例
Android-JNI完整工程,实现c调用java和java调用c
利用JNI技术实现Java中调用C++编写的函数库示例程序源码,并附上参考JNI文档。 详情见本人博客:Java学习之通过JNI调用C/C++编写的dll链接库(图文教程)(http://write.blog.csdn.net/postlist)
完整的实现java跨平台调用C程序源码,包含JAVA源码和C源码以及编译后的demo dll。将dll放到jdk bin目录下,java 项目可以直接运行。若要修改dll可以,修改C源码后重新编译生成dll。该demo处理了多线程调用c,全局...
android jni native C++访问java层数组,java类对象属性和方法,回调接口和线程回调接口 内附可以正常使用的demo
jni之c++和java互编,内部含有jni的实例,内有java调用c++,c++调用java的代码
JNI的API参考手册 博文链接:https://chnic.iteye.com/blog/236248
这是一个简单的JNI开发中C层调用Java层函数的事例工程,对应的博客地址是:http://blog.csdn.net/hty1053240123/article/details/52126386
完整的展示了Java调用C++ API/dll示例程序. 说明如下: 1. mrSocketAPICInt是准备被java调用的API 2. mrSocketAPIJavaInt是java调用C++ api的中间层 3. mrSocketAPIJavaIntDemo是java程序,展示与C++ api如何对接。...
JNI调用C++代码和C++层回调java层 demo
这是一个Android Tcp客户端测试程序,底层由C++实现收发,通过JNI实现C++与JAVA相互调用。本程序完成最基本的收发功能,希望下载的人完善程序后再发布共享到这里。
简单的通过jni在C/C++中调用Java的例子