C++ 调用 java 创建对象

【1】http://www.ccidnet.com/2005/0413/237901.shtml

【2】http://public0821.iteye.com/blog/423941



【3】http://blog.csdn.net/sf0407/article/details/53924174  

简单的C++加载jvm实现

这篇文章基本上是靠谱的。有几处小问题:包含文件有两个:jni.h  jni_md.h,复制到工程目录下。


【4】如何获取 java class 的签名:https://jingyan.baidu.com/article/d2b1d102b67a905c7e37d425.html


【5】找不到  javap 命令怎么办:https://jingyan.baidu.com/article/1e5468f924210a484961b7f0.html

it Works !

C:\Users\galax\AndroidStudioProjects\testjar2\myjar\build\intermediates\classes\debug\com\eonsoft\android\myjar>javap -s Main.class
Compiled from "Main.java"
public class com.eonsoft.android.myjar.Main {
  public com.eonsoft.android.myjar.Main();
    descriptor: ()V

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V

  public java.lang.String getString(java.lang.String);
    descriptor: (Ljava/lang/String;)Ljava/lang/String;
}


【6】:【2】【3】的代码都堪用,但是函数名有讲究,象上面那个函数 getString ,可能是和系统函数重名,死活无法 GetMethodID 返回 NULL ,改名后正常。




亲测有效代码:

CString XXX::startJVM(void) {
	CString rslt = "";
	//获取jvm动态库的路径
	TCHAR* jvmPath = _T("C://Program Files//Java//jdk1.8.0_151//jre//bin//server//jvm.dll");
	
	int nOptionCount = 2;//java虚拟机启动时接收的参数,每个参数单独一项
	
	JavaVMOption vmOption[2];
	vmOption[0].optionString = "-Xmx256M";//设置JVM最大允许分配的堆内存,按需分配
	vmOption[1].optionString = "-Djava.class.path=./mysdk.jar";//设置classpath

	JavaVMInitArgs vmInitArgs;
	vmInitArgs.version = JNI_VERSION_1_8;
	vmInitArgs.options = vmOption;
	vmInitArgs.nOptions = nOptionCount;
	vmInitArgs.ignoreUnrecognized = JNI_TRUE;//忽略无法识别jvm的情况
	
	const char nameMainClass[] = "com/XXXX/XXXX/myjar/Main";//设置启动类,注意分隔符为"/"
	
	//加载JVM,注意需要传入的字符串为LPCWSTR,指向一个常量Unicode字符串的32位指针,相当于const wchar_t*
	HINSTANCE jvmDLL = LoadLibrary(jvmPath);
	if (jvmDLL == NULL) {
		return "加载JVM动态库错误" + ::GetLastError();
	}

	//初始化jvm物理地址
	JNICREATEPROC jvmProcAddress = (JNICREATEPROC)GetProcAddress(jvmDLL, "JNI_CreateJavaVM");
	if (jvmDLL == NULL) {
		FreeLibrary(jvmDLL);
		return "初始化jvm物理地址错误" + ::GetLastError();
	}

	//创建JVM
	JNIEnv *env;
	JavaVM *jvm;
	jint jvmProc = (jvmProcAddress)(&jvm, (void **)&env, &vmInitArgs);
	if (jvmProc < 0 || jvm == NULL || env == NULL) {
		FreeLibrary(jvmDLL);
		return "创建JVM错误" + ::GetLastError();
	}

	//加载启动类
	jclass mainclass = env->FindClass(nameMainClass);
	if (env->ExceptionCheck() == JNI_TRUE || mainclass == NULL) {
		env->ExceptionDescribe();
		env->ExceptionClear();
		FreeLibrary(jvmDLL);
		return "加载启动类失败";
	}

	//获取类中的方法,最后一个参数是方法的签名,通过javap -s -p 文件名可以获得  
	jmethodID mid1 = env->GetStaticMethodID(mainclass, "main", "([Ljava/lang/String;)V");
	if (env->ExceptionCheck() == JNI_TRUE || mid1 == NULL) {
		env->ExceptionDescribe();
		env->ExceptionClear();
		FreeLibrary(jvmDLL);
		return "加载启动方法失败-main-stactic";
	}
	rslt.Format(_T(";mid1=%d"),   mid1);
	
	//获取类中的方法,最后一个参数是方法的签名,通过javap -s -p 文件名可以获得  
	jmethodID mid = env->GetMethodID(mainclass, "getString2", "(Ljava/lang/String;)Ljava/lang/String;");
	if (env->ExceptionCheck() == JNI_TRUE || mid == NULL) {
		env->ExceptionDescribe();
		env->ExceptionClear();
		FreeLibrary(jvmDLL);
		rslt += "加载启动方法失败-getString";
		return rslt;
	}
	CString temp = "";
	temp.Format(_T(";mid=%d"), mid);
	rslt += temp;
	//调用对象的方法
	jobject obj = env->AllocObject(mainclass);//根据类的CLASS对象获取该类的实例
	const char szTest[] = "f";//构造参数
	jstring arg = str2jstring(env, szTest);
	jstring msg = (jstring)env->CallObjectMethod(obj, mid, arg);
	rslt += jstring2CString(env, msg);
	return rslt;
}

应注意:下面这段代码要放在使用之前,否则编译会报找不到定义。

CString CDynamicTyperJar::jstring2CString(JNIEnv *m_penv, jstring jnistr)
{
	//      We modified in this function because we founf if the length is of two chars
	//      it add a rubish char concatenated at the end of the string

	CString            dummyCString, retCString;
	jsize            istringlength;

	jboolean isCopy = JNI_TRUE;
	const jchar *pChar = m_penv->GetStringChars(jnistr, &isCopy);
	istringlength = m_penv->GetStringLength(jnistr);
	dummyCString = (BSTR)pChar;
	retCString = dummyCString.Mid(0, istringlength);
	m_penv->ReleaseStringChars(jnistr, pChar);

	return retCString;
}

jstring CDynamicTyperJar::str2jstring(JNIEnv* env, const char* pat)
{
	jclass strClass = env->FindClass("Ljava/lang/String;");
	jmethodID ctorID = env->GetMethodID(strClass, "<init>", "([BLjava/lang/String;)V");
	jbyteArray bytes = env->NewByteArray(strlen(pat));
	env->SetByteArrayRegion(bytes, 0, strlen(pat), (jbyte*)pat);
	jstring encoding = env->NewStringUTF("utf-8");
	return (jstring)env->NewObject(strClass, ctorID, bytes, encoding);
}





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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值