linux下jni调用java代码

之前研究了一下jni调用c++的初级使用,今天研究一下jni调用java,下面的文章给了我很大帮助

http://www.360doc.com/content/12/1210/21/9171956_253297297.shtml


jni调用c++过程可以分为这几步:

1. 初始化虚拟机

2. 获取类和实例

3. 获取函数并执行

4 .销毁虚拟机


我按照以上的思想对调用java代码的过程进行c++封装, 但是在封装call函数的时候卡住了, 由于参数列表的原因,还没有想好如何封装. 这将在以后解决


首先贴出main函数代码

#include "JNIClass.h"

int main(int argc, char* argv[])
{
	 CJNI jni;
	 jni.init();
	 jni.getClassAndInstance("Jnitest");
	 jni.runMethod("output_two",NULL,2,'d',true);
	 return 0;
}

其中,CJNI类是对JNI接口的简单封装, init()负责初始化虚拟机, getClassAndInstance则根据传入的类名进行查找和创建实例,runMethod则根据参数调用相应的参数,这个还没有解决. main函数结束时自动销毁虚拟机


下面来看看CJNI类的定义

#include <jni.h>
#include <map>
#include <string>
using std::string;
using std::map;
	
#define CJNI_CREATEJVM_FAIL  0x0001			//创建虚拟机失败
#define CJNI_GETTHREAD_FAIL  0x0002 		//获取线程运行环境失败
#define CJNI_GETCLASS_FAIL   0x0003			//获取类失败
#define CJNI_INITCLASS_FAIL  0x0004			//初始化类失败
#define CJNI_OK 	     0x0000		//运行成功
#define CJNI_RUN_FAIL 	     0x0005		//执行函数失败
#define CJNI_GETINFO_FAIL    0x0006		//获取信息失败

class CJNI
{
	public:
	  	CJNI();
	 	~CJNI();
		int init();					//初始化
		int getClassAndInstance(const char*);		//获取类对象
		//int runMethod(const char*,void* = NULL,int = 0,...);
		//int runStaticMethod(const char*,void* = NULL,int = 0,...);
	private:
		int getClassInfo(const char*);
	private:
		JNIEnv *env;
	  	JavaVM *jvm;
	  	JavaVMInitArgs vm_args;
	  	JavaVMOption *options;
	 	jclass gotClass;			      //当前获取的类
	  	jobject gotInstance;        	//当前获取的类实例
	  	map<string,string> methodParas; //当前类函数信息
};


CJNI类的实现

#include "JNIClass.h"
#include <stdio.h>   
#include <cstdarg> 
#include <string.h>
#include <iostream>
#include <stdlib.h>
using std::cout;
using std::endl;

CJNI::CJNI()
{
}

CJNI::~CJNI()
{
	 delete options;
	 
	 jvm ->DestroyJavaVM();
	 
}

int CJNI::init()
{
	options = new JavaVMOption[2];
	options[0].optionString = "-Djava.compiler=NONE";
	options[1].optionString = "-Djava.class.path=./java";
	//options[2].optionString = "-verbose:jni";
	
	vm_args.version = JNI_VERSION_1_6;
	vm_args.nOptions = 2;
	vm_args.options = options;
	vm_args.ignoreUnrecognized = JNI_TRUE;
	
	if(0 != JNI_CreateJavaVM(&jvm, (void**)&env,&vm_args))
		return CJNI_CREATEJVM_FAIL;
	if(0 != jvm -> AttachCurrentThread(reinterpret_cast<void**>(&env),(void*)NULL))
		return CJNI_GETTHREAD_FAIL;
		
	return CJNI_OK;
}

//@className  包名+类名
int CJNI::getClassAndInstance(const char* className)
{
   //查找类
  gotClass = env -> FindClass(className);
  if(gotClass == 0)
  	 return CJNI_GETCLASS_FAIL;

  //初始化类
  jmethodID ctor = env -> GetMethodID(gotClass,"<init>","()V");
  if(0 == ctor)
  	return CJNI_INITCLASS_FAIL;
 
  //创建实例
  gotInstance = env -> NewObject(gotClass,ctor);
  
  //获取函数定义
  return getClassInfo(className);;
}	

//@methodName 函数名
//@output			返回结果
//@num				参数个数
//@...				参数列表
int CJNI::runMethod(const char* methodName,void* output,int num,...)
{
	char len[10];
	sprintf(len,"%d",num);
	string value = methodParas.find(len + string(methodName)) -> second;
	cout << value << endl;
	 //查找对应函数
//	 char arglist[100];
//	 va_list argptr;
//	 int cnt;
//	 va_start(argptr, fmt);
//   cnt = vsprintf(arglist, fmt, argptr);
//   va_end(argptr);

//	 jmethodID methodID = env -> GetMethodID(gotClass,methodName,"()V");
//   if(methodID == 0)
//  		return CJNI_RUN_FAIL;
//  		
//   env -> CallVoidMethod(gotInstance,methodID);
//  	 if(env ->ExceptionOccurred())
//  	 {
//  	 	  env->ExceptionDescribe();
//  	 	  env->ExceptionClear();
//  	 	  return 0;
//  	 }
  	 
    return CJNI_OK;
}

//@methodName 函数名
//@output			返回结果
//@num				参数个数
//@...				参数列表
int CJNI::runStaticMethod(const char* methodName,void* output,int num,...)
{
	  //jmethodID mid = env->GetStaticMethodID( JavaClass, "output_one", "()V");
  	//env -> CallStaticVoidMethod(JavaClass,mid);
  	return CJNI_OK;
}

//获取类中函数的信息, 调用此函数就不需要使用javap
//信息格式如下, 与javap命令产生结果一致
//	Compiled from "Jnitest.java"
//	public class Jnitest extends java.lang.Object{
//	public Jnitest();
//  	Signature: ()V
//	public static void output_one();
//  	Signature: ()V
//	public void output_two();
//  	Signature: ()V
//}
int CJNI::getClassInfo(const char* className)
{
	 char cmd[256];
	 char line[200];
   FILE* fp;
   int nfunc = 0;    //函数个数
   string func_name, func_para;
   char len[10];
   
   sprintf(cmd, "javap -s -p java/%s", className);
   fp=popen(cmd, "r");
   if(fp == NULL)
        return CJNI_GETINFO_FAIL;
        
   //读取数据
   while(NULL != fgets(line,200,fp))
   {
   	  int pos;
   	  string tmp(line);
   	  //printf(":%s",tmp.c_str());

   	  if(string::npos != (pos = tmp.find("Signature: ")))
   	 { 
   	 	 //函数参数
   	 	  int lpos = tmp.find("(");
   	 	  int rpos = tmp.find(")") + 1;
   	 	  sprintf(len,"%d",rpos - lpos - 2);
   	  	func_para = tmp.substr(lpos,rpos - lpos + 1); 
   	  	func_name = len + func_name;
   	  	methodParas.insert(map<string, string>::value_type(func_name,func_para));  
   	 }
   	  else if(string::npos != (pos = tmp.find("(")))
   	 {
   	 	 //函数名
   	 	  int rpos = pos - 1;
   	 	  int lpos = tmp.find_last_of(" ", rpos) + 1;
   	 	  func_name = tmp.substr(lpos,rpos - lpos + 1);
   	 }	
   	 
   	 //memset(line,'\0',200);
   }
   pclose(fp);
   
   return CJNI_OK;
}

 
其中runStaticMethod和runMethod没实现完整. getClassInfo实现了javap的功能,所以不需要手动去javap. 在调用init()后正常的调用函数过程为根据函数类型的不同调用对应的函数,比如静态函数调用CallStaticVoidMethod,类函数调用CallVoidMethod. 在此就不一一细讲, 文章开头贴出的链接讲的很不错了,大家可以看一看,下面贴出我用来测试流程的代码,跟链接中的代码很相似

#include <jni.h>
#include <iostream>
using std::cout;
using std::endl;
	
int main()
{
	JNIEnv *env;
	JavaVM *jvm;
	JavaVMInitArgs vm_args;
	JavaVMOption options[3];
	int res;
	//初始化虚拟机
	//设置参数
	options[0].optionString = "-Djava.compiler=NONE";
	options[1].optionString = "-Djava.class.path=./java";
	//options[2].optionString = "-verbose:jni";

	vm_args.version = JNI_VERSION_1_6;
	vm_args.nOptions = 2;
	vm_args.options = options;
	vm_args.ignoreUnrecognized = JNI_TRUE;
	res = JNI_CreateJavaVM(&jvm, (void**)&env,&vm_args);
	
	if(res == 0)
	{
		 cout << "create jvm success!" << endl;
  }else
  {
  	 cout << "create jvm failed!" << endl;
  }
  
  int result = jvm -> AttachCurrentThread(reinterpret_cast<void**>(&env),(void*)NULL);
  if(result == 0)
  {
  	 cout << "get env success!" << endl;
  }else
  {
  	 cout << "get env failed!" << endl;
  }
  
  //获取类/
  jclass JavaClass;
  jobject obj1;
  JavaClass = env -> FindClass("Jnitest");
  if(JavaClass != 0)
  {
  	 cout << "get java class success!" << endl;
  	 //执行静态方法
  	 jmethodID mid = env->GetStaticMethodID( JavaClass, "output_one", "()V");
  	 env -> CallStaticVoidMethod(JavaClass,mid);
  }else
  {
  	 cout << "get java class failed!" << endl;
  }
  ///创建类对象///
  jobject obj;
  jmethodID ctor;
  ctor = env -> GetMethodID(JavaClass,"<init>","()V");
  if(ctor != 0)
  {
  	 obj = env -> NewObject(JavaClass,ctor);
  	 cout << "get java method success!" << endl;
  }else
  {
  	 cout << "get java method failed!" << endl;
  }
  
  ///调用方法/
  jmethodID methodID = env -> GetMethodID(JavaClass,"output_two","()V");
  if(methodID != 0)
  {
  	 env -> CallVoidMethod(obj,methodID);
  	 if(env ->ExceptionOccurred())
  	 {
  	 	  env->ExceptionDescribe();
  	 	  env->ExceptionClear();
  	 	  jvm ->DestroyJavaVM();
  	 	  return 0;
  	 }
  }
  /退出虚拟机/
  jvm ->DestroyJavaVM();
	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值