#include <windows.h>
#include <jni.h> //#pragma comment( linker, "/subsystem:"console" /entry:"mainCRTStartup"" ) #pragma comment( linker, "/subsystem:"windows" /entry:"WinMainCRTStartup"" ) typedef jint (JNICALL *JNICREATEPROC)(JavaVM **, void **, void *); bool setStream(JNIEnv *env, const char* pszFileName, const char* pszMethod); //啓動java虛擬機方法 //bool main(int argc,char *argv[]) int WINAPI WinMain (HINSTANCE hInst, HINSTANCE hPrevInstance,PSTR szCmdLine, int iCmdShow) { //jvm動態庫的路徑 const char szJvmPath[] = "d:/jdk1.5.0_07/jre/bin/server/jvm.dll"; //java 虛擬機的啓動參數,每個參數寫一項,不能合在一起寫 int nOptionCount = 2; JavaVMOption options[2]; options[1].optionString = "-Xmx256M"; //設置classpath options[0].optionString = "-Djava.class.path=./Test.exe"; JavaVMInitArgs vm_args; vm_args.version = JNI_VERSION_1_4; vm_args.options = options; vm_args.nOptions = nOptionCount; vm_args.ignoreUnrecognized = JNI_TRUE; //啓動類,注意分割符是/,例如啓動類test.JTest應該寫成 test/JTest const char szStartClass[] = "com/primeton/test/TestClass"; //啓動方法,通常是main函數,你也可以設定成其他函數 const char szStartMethod[] = "main"; //重導向文件 const char szStdoutFileName[] = "stdout.txt"; const char szStderrFileName[] = "stderr.txt"; //java程序的命令行參數 int nParamCount = 2; const char *szParams[2] = {"arg1","arg2"}; //加載JVM。 HINSTANCE jvmDll = LoadLibrary(szJvmPath); if (jvmDll == NULL) { printf("加載JVM動態庫錯誤。%l", ::GetLastError()); return false; } //查找JNI_CreateJavaVM過程。 JNICREATEPROC jvmCreateProc = (JNICREATEPROC)GetProcAddress(jvmDll, "JNI_CreateJavaVM"); if (jvmCreateProc == NULL) { FreeLibrary(jvmDll); printf("查找JNI_CreateJavaVM過程錯誤。%l", ::GetLastError()); return false; } //創建JVM。 JNIEnv *env; JavaVM *jvm; jint r = (jvmCreateProc)(&jvm, (void **)&env, &vm_args); if (r < 0 || jvm == NULL || env == NULL) { FreeLibrary(jvmDll); printf( "創建JVM發生錯誤。"); return false; } //重導向stdout, stderr到輸出文件 if (!setStream(env, szStdoutFileName, "setOut")) { printf("設置stdout輸出文件失敗"); return false; } if (!setStream(env, szStderrFileName, "setErr")) { printf("設置stderr輸出文件失敗"); return false; } //加載啓動類。 jclass serviceClass = env->FindClass(szStartClass); if (env->ExceptionCheck() == JNI_TRUE || serviceClass == NULL) { env->ExceptionDescribe(); env->ExceptionClear(); FreeLibrary(jvmDll); printf("加載啓動類失敗。"); return false; } //啓動方法 jmethodID mid = env->GetStaticMethodID(serviceClass, szStartMethod , "([Ljava/lang/String;)V"); if (env->ExceptionCheck() == JNI_TRUE || mid == NULL) { env->ExceptionDescribe(); env->ExceptionClear(); FreeLibrary(jvmDll); printf("查找啓動方法失敗。"); return false; } //查找String類。 jclass stringClass = env->FindClass("java/lang/String"); if (env->ExceptionCheck() == JNI_TRUE || stringClass == NULL) { env->ExceptionDescribe(); env->ExceptionClear(); FreeLibrary(jvmDll); printf("查找String類失敗。"); return false; } jstring jstr; jobjectArray args = 0; args = env->NewObjectArray(2, stringClass, 0); for (int i=0; i<nParamCount; i++) { jstr = env->NewStringUTF(szParams[i]); if (jstr == 0) { printf("分配String失敗 "); if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear(); } return false; } env->SetObjectArrayElement(args, i, jstr); if (env->ExceptionCheck() == JNI_TRUE) { printf("設置參數失敗 "); if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear(); } return false; } } //調用啓動類的啓動方法啓動Java程序 //env->CallStaticVoidMethod(serviceClass, mid, parameterArray); env->CallStaticVoidMethod(serviceClass, mid, args); if (env->ExceptionCheck() == JNI_TRUE) { env->ExceptionDescribe(); env->ExceptionClear(); FreeLibrary(jvmDll); return false; } MSG msg ; while (GetMessage (&msg, NULL, 0, 0)) { TranslateMessage (&msg) ; DispatchMessage (&msg) ; } return true; } //設置輸出流的方法 bool setStream(JNIEnv *env, const char* pszFileName, const char* pszMethod) { int pBufferSize = 1024; char* pBuffer = new char[pBufferSize]; //創建字符串對象。 jstring pathString = env->NewStringUTF(pszFileName); if (env->ExceptionCheck() == JNI_TRUE || pathString == NULL) { env->ExceptionDescribe(); env->ExceptionClear(); printf("創建字符串失敗。"); return false; } //查找FileOutputStream類。 jclass fileOutputStreamClass = env->FindClass("java/io/FileOutputStream"); if (env->ExceptionCheck() == JNI_TRUE || fileOutputStreamClass == NULL) { env->ExceptionDescribe(); env->ExceptionClear(); printf("查找FileOutputStream類失敗。"); return false; } //查找FileOutputStream類構造方法。 jmethodID fileOutputStreamConstructor = env->GetMethodID(fileOutputStreamClass, "<init>", "(Ljava/lang/String;)V"); if (env->ExceptionCheck() == JNI_TRUE || fileOutputStreamConstructor == NULL) { env->ExceptionDescribe(); env->ExceptionClear(); printf("查找FileOutputStream類構造方法失敗。"); return false; } //創建FileOutputStream類的對象。 jobject fileOutputStream = env->NewObject(fileOutputStreamClass, fileOutputStreamConstructor, pathString); if (env->ExceptionCheck() == JNI_TRUE || fileOutputStream == NULL) { env->ExceptionDescribe(); env->ExceptionClear(); printf("創建FileOutputStream類的對象失敗。"); return false; } //查找PrintStream類。 jclass printStreamClass = env->FindClass("java/io/PrintStream"); if (env->ExceptionCheck() == JNI_TRUE || printStreamClass == NULL) { env->ExceptionDescribe(); env->ExceptionClear(); printf("查找PrintStream類失敗。"); return false; } //查找PrintStream類構造方法。 jmethodID printStreamConstructor = env->GetMethodID(printStreamClass, "<init>", "(Ljava/io/OutputStream;)V"); if (env->ExceptionCheck() == JNI_TRUE || printStreamConstructor == NULL) { env->ExceptionDescribe(); env->ExceptionClear(); printf("查找PrintStream類構造方法失敗。"); return false; } //創建PrintStream類的對象。 jobject printStream = env->NewObject(printStreamClass, printStreamConstructor, fileOutputStream); if (env->ExceptionCheck() == JNI_TRUE || printStream == NULL) { env->ExceptionDescribe(); env->ExceptionClear(); printf("創建PrintStream類的對象失敗。"); return false; } //查找System類。 jclass systemClass = env->FindClass("java/lang/System"); if (env->ExceptionCheck() == JNI_TRUE || systemClass == NULL) { env->ExceptionDescribe(); env->ExceptionClear(); printf( "查找System類失敗。"); return false; } //查找System類設置方法。 jmethodID setStreamMethod = env->GetStaticMethodID(systemClass, pszMethod, "(Ljava/io/PrintStream;)V"); if (env->ExceptionCheck() == JNI_TRUE || setStreamMethod == NULL) { env->ExceptionDescribe(); env->ExceptionClear(); printf("查找System類設置方法失敗。"); return false; } //設置System類的流。 env->CallStaticVoidMethod(systemClass, setStreamMethod, printStream); if (env->ExceptionCheck() == JNI_TRUE) { env->ExceptionDescribe(); env->ExceptionClear(); printf("設置System類的流失敗。"); return false; } return true; } |