在編程的學習過程中,愈發感覺到了女性思維在這方面的局限性。
背景介紹:
為了學習JNI中C++對Java的調用,在閱讀《JNI技術手冊》的同時加以練習。但根據示例代碼編寫過程中總出現各種
奇怪的問題(一度后悔自己裝了win7 64位系統,而電腦之前是預裝win8 32位的...)。由於Java部分的代碼非常簡單,
沒有出現任何錯誤,javac、javah命令也能正常輸出.class文件和頭文件。但C++部分卻報錯了。所學習的示例代碼意圖
通過C++調用Java,生成一個.exe的啟動文件。
Java代碼如下:
1 public class C2Java { 2 3 public C2Java(){ 4 super(); 5 } 6 7 public static int add(int a,int b){ 8 return a+b; 9 } 10 11 public boolean judge(boolean bool){ 12 return !bool; 13 } 14 }
C++代碼如下:
// c2java.cpp : 定義控制台應用程序的入口點。 #include "stdafx.h" #include "windows.h" using namespace std; int main(int argc, char* argv[]) { JavaVMOption options[1]; JNIEnv *env; JavaVM *jvm; JavaVMInitArgs vm_args; long status; jclass cls; jmethodID mid; jint square; jboolean not; jobject jobj; options[0].optionString = "-Djava.class.path=."; vm_args.version = JNI_VERSION_1_6; vm_args.nOptions = 1; vm_args.options = options; vm_args.ignoreUnrecognized = JNI_TRUE; status = JNI_CreateJavaVM(&jvm,(void**)&env,&vm_args); if(status != JNI_ERR) { cls = env->FindClass("C2Java"); if(cls !=0) { mid = env->GetStaticMethodID(cls, "add", "(II)I"); if(mid !=0) { square = env->CallStaticIntMethod(cls, mid, 5, 5); std::cout << square << std::endl; } mid = env->GetMethodID(cls, "<init>", "()V"); if(mid !=0) { jobj=env->NewObject(cls, mid); std::cout << "init ok"<< std::endl; } mid = env->GetMethodID(cls, "judge", "(Z)Z"); if(mid !=0) { not= env->CallBooleanMethod(jobj, mid, 1); if(!not) { std::cout << "Boolean ok"<< std::endl; } } } jvm->DestroyJavaVM(); return 0; } else return -1; }
由於創建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++代碼相關部分修改為:
//定義一個函數指針,下面用來指向JVM中的JNI_CreateJavaVM函數 typedef jint (WINAPI *PFunCreateJavaVM)(JavaVM **, void **, void *); const char szJvmPath[] = "C:\\Program Files\\Java\\jdk1.7.0_51\\jre\\bin\\server\\jvm.dll"; HINSTANCE hInstance = ::LoadLibrary(szJvmPath); if (hInstance == NULL) { cout<< "LoadLibrary False"<<endl; cout<<::GetLastError()<<endl; return -2; } //取得里面的JNI_CreateJavaVM函數指針 PFunCreateJavaVM funCreateJavaVM = (PFunCreateJavaVM)::GetProcAddress(hInstance, "JNI_CreateJavaVM"); status = (*funCreateJavaVM)(&jvm, (void**)&env, &vm_args);
運行后返回值為-2,GetLastError的內容為193,意思是動態加載dll文件失敗了。設置斷點查看各變量內容時,發現LoadLibrary的返回值為空。查閱資料后
進行修改仍不能正常運行。目前還未找到方法來成功解決此問題T.T
運行。
快拯救我吖神奇的博客園... 只希望每次愚蠢的錯誤都能深深印刻在我的腦海里……
