<track id="1rt7t"></track>
<pre id="1rt7t"></pre>

    <p id="1rt7t"><ruby id="1rt7t"><b id="1rt7t"></b></ruby></p>

      軟件培訓網

      歡迎訪問軟件培訓網!招生咨詢電話與微信:15225191462(周老師)
      軟件培訓網,專業解決學IT疑難雜癥!

      首頁 > java > java教程/ 正文

      將Java代碼打包為exe文件

      2014-02-25 16:31:29 Java培訓

       1       基本信息qPK軟件培訓網

      摘要:
                現在有很多的工具將Java代碼打包為exe文件,執行時不需要再編寫批處理文件,或者在命令行輸入長長的classpath信息,為用戶使用提供了很大的方便。這也是很多商業軟件常常使用的方法。
      作者:晏斐 
      2       將Java代碼打包為exe文件
             現在有很多的工具將Java代碼打包為exe文件,執行時不需要再編寫批處理文件,或者在命令行輸入長長的classpath信息,為用戶使用提供了很大的方便。這也是很多商業軟件常常使用的方法。
             將Java代碼打包為exe文件,一般需要兩個步驟:
      1.       編寫本地代碼,創建虛擬機,加載并執行Main Class。
      2.       將Java代碼打包為jar文件,并與本地代碼exe文件合并。
      下面的代碼,會加載jvm.dll,并調用JNI_CreateJavaVM導出函數創建Java虛擬機,得到JNIEnv指針,然后調用FindClass查找Main Class,之后調用GetStaticMethodID方法得到main方法,并執行main方法。代碼如下:
      #include <windows.h>
      #include <jni.h>
      //#pragma comment( linker, "/subsystem:"console" /entry:"mainCRTStartup"" ) 
      #pragma comment( linker, "/subsystem:"windows" /entry:"WinMainCRTStartup"" ) 
      qPK軟件培訓網
      typedef jint (JNICALL *JNICREATEPROC)(JavaVM **, void **, void *);
      bool setStream(JNIEnv *env, const char* pszFileName, const char* pszMethod);
      //啟動java虛擬機方法
      qPK軟件培訓網
      //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_07jreinserverjvm.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;
          
      }
      qPK軟件培訓網
      //設置輸出流的方法
      qPK軟件培訓網
      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;
      }
       
      第二步,將Java文件打包為exe文件,也很簡單。在Dos提示符下執行copy命令:
      C:>copy test.exe+test.jar test.exe
      其實,就是將Java打包文件追加到exe文件尾部。打開文件屬性對話框,可看到有“壓縮文件”屬性頁。老牌的JBuilder.exe開發工具編譯生成的exe文件即采用如下方式生成。
      后記:大家在使用Eclipse 3.2和Eclipse 3.3時,在任務管理器中會看到二者的不同。Eclipse 3.2是先啟動Eclipse.exe文件,然后由Eclipse.exe啟動Javaw.exe文件來創建虛擬機。
      Eclipse 3.2在任務管理器中顯示為Eclipse.exe和javaw.exe兩個進程。
      Eclipse 3.3在任務管理器中顯示為Eclipse.exe一個進程。
      從上面可以看出,Eclipse 3.2和Eclipse 3.3采用了不同的虛擬機加載方式。
       
      Eclipse 3.2采用創建子進程的方法調用javaw.exe來啟動,在windows下面可以用CreateProcess方法,此種方法較簡單,具體可參見Eclipse源碼。
       
      Eclipse 3.3加載java虛擬機的另外一種方法是加載jvm的動態庫,并通過動態庫的接口來在本進程內啟動java虛擬機。本文開頭即采用的第二種方法。

      Tags:女生學習編程容易嗎,鄭州學游戲軟件編程培訓學校有哪些,鄭州北大青鳥java培訓怎么樣,鄭州北大青鳥學軟件開發需要什么基礎,鄭州計算機java專業學校,鄭州北大青可以拿java工程師證嗎

      更多女生學習編程容易嗎,鄭州學游戲軟件編程培訓學校有哪些,鄭州北大青鳥java培訓怎么樣,鄭州北大青鳥學軟件開發需要什么基礎,鄭州計算機java專業學校,鄭州北大青可以拿java工程師證嗎相關文章

      搜索
      軟件培訓學校哪家好,就來軟件培訓網咨詢
      軟件培訓學校哪家好,就來軟件培訓網咨詢
      軟件培訓學校哪家好,就來軟件培訓網咨詢
      軟件培訓學校哪家好,就來軟件培訓網咨詢
      • QQ交談
      制服丝袜无码中文字幕第1页

      <track id="1rt7t"></track>
      <pre id="1rt7t"></pre>

        <p id="1rt7t"><ruby id="1rt7t"><b id="1rt7t"></b></ruby></p>