在编程的学习过程中,愈发感觉到了女性思维在这方面的局限性。

背景介绍:

  为了学习JNI中C++对Java的调用,在阅读《JNI技术手册》的同时加以练习。但根据示例代码编写过程中总出现各种

奇怪的问题(一度后悔自己装了win7 64位系统,而电脑之前是预装win8 32位的…)。由于Java部分的代码非常简单,

没有出现任何错误,javac、javah命令也能正常输出.class文件和头文件。但C++部分却报错了。所学习的示例代码意图

通过C++调用Java,生成一个.exe的启动文件。

  Java代码如下:    

  1. 1 public class C2Java {
  2. 2
  3. 3 public C2Java(){
  4. 4 super();
  5. 5 }
  6. 6
  7. 7 public static int add(int a,int b){
  8. 8 return a+b;
  9. 9 }
  10. 10
  11. 11 public boolean judge(boolean bool){
  12. 12 return !bool;
  13. 13 }
  14. 14 }

  C++代码如下: 

  1. // c2java.cpp : 定义控制台应用程序的入口点。
  2. #include "stdafx.h"
  3. #include "windows.h"
  4.  
  5. using namespace std;
  6. int main(int argc, char* argv[])
  7. {
  8. JavaVMOption options[1];
  9. JNIEnv *env;
  10. JavaVM *jvm;
  11. JavaVMInitArgs vm_args;
  12. long status;
  13. jclass cls;
  14. jmethodID mid;
  15. jint square;
  16. jboolean not;
  17. jobject jobj;
  18. options[0].optionString = "-Djava.class.path=.";
  19. vm_args.version = JNI_VERSION_1_6;
  20. vm_args.nOptions = 1;
  21. vm_args.options = options;
  22. vm_args.ignoreUnrecognized = JNI_TRUE;
  23. status = JNI_CreateJavaVM(&jvm,(void**)&env,&vm_args);
  24. if(status != JNI_ERR) {
  25. cls = env->FindClass("C2Java");
  26. if(cls !=0) {
  27. mid = env->GetStaticMethodID(cls, "add", "(II)I");
  28. if(mid !=0) {
  29. square = env->CallStaticIntMethod(cls, mid, 5, 5);
  30. std::cout << square << std::endl;
  31. }
  32. mid = env->GetMethodID(cls, "<init>", "()V");
  33. if(mid !=0) {
  34. jobj=env->NewObject(cls, mid);
  35. std::cout << "init ok"<< std::endl;
  36. }
  37. mid = env->GetMethodID(cls, "judge", "(Z)Z");
  38. if(mid !=0) {
  39. not= env->CallBooleanMethod(jobj, mid, 1);
  40. if(!not) {
  41. std::cout << "Boolean ok"<< std::endl;
  42. }
  43. }
  44. }
  45. jvm->DestroyJavaVM();
  46. return 0;
  47. } else
  48. return -1;
  49. }

  由于创建jvm过程中可以通过两种方式加载jvm.dll动态链接库文件,在两种方式的尝试中发现了截然不同的错误。

  错误内容:

  错误1:使用如上代码,通过在path中添加jvm.dll路径、在工程/属性/链接器/输出中添加jvm.lib依赖库,实现dll文件的静态加载。反复测试了很多次,

始终报错如下:

  单步调试似乎也不能使用,查阅相关资料,将console改为window报的错更多…… 之后又仔细搜寻相关教程,根据:http://andy-li-chn.iteye.com/blog/1175075

的说法:“自定义的类JVM无法找到,例子只说让自己编写自定义的类,但并没有说生成的类应该放在什么地方才可以被JVM正确的找到。通常根据需要我们的类是放在特定

的目录下的,而且放在jvm路径下也是不安全的,所以在网上的大多数例子都缺少一步,设置自定义类的路径 “。根据这个思路,决定自定义类路径并动态加载dll文件。

 错误2: 将自己的C++代码相关部分修改为:

  1.   //定义一个函数指针,下面用来指向JVM中的JNI_CreateJavaVM函数
  2. typedef jint (WINAPI *PFunCreateJavaVM)(JavaVM **, void **, void *);
  3.   const char szJvmPath[] = "C:\\Program Files\\Java\\jdk1.7.0_51\\jre\\bin\\server\\jvm.dll";
  4. HINSTANCE hInstance = ::LoadLibrary(szJvmPath);
  5. if (hInstance == NULL)
  6. {
  7. cout<< "LoadLibrary False"<<endl;
  8. cout<<::GetLastError()<<endl;
  9. return -2;
  10. }
  11. //取得里面的JNI_CreateJavaVM函数指针
  12. PFunCreateJavaVM funCreateJavaVM = (PFunCreateJavaVM)::GetProcAddress(hInstance, "JNI_CreateJavaVM");
  13. status = (*funCreateJavaVM)(&jvm, (void**)&env, &vm_args);

  运行后返回值为-2,GetLastError的内容为193,意思是动态加载dll文件失败了。设置断点查看各变量内容时,发现LoadLibrary的返回值为空。查阅资料后

进行修改仍不能正常运行。目前还未找到方法来成功解决此问题T.T

运行。

  快拯救我吖神奇的博客园… 只希望每次愚蠢的错误都能深深印刻在我的脑海里……

版权声明:本文为annaivsu原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/annaivsu/p/3959175.html