在C++程式碼中建立Java虛擬機器。
好多人都在問如何將java程式碼打包成exe檔案,其實,下面這段程式碼稍微修改一下就可以做一個類似Java2Exe的功能。
順便看了一下JBuilder編譯生成的exe檔案(星期天半天的時間花在研究這個上面了),是將jar檔案追加到exe檔案末尾,然後將exe檔案當作jar檔案來使用,因此,除錯了半天也沒發現它寫臨時檔案。方法還是挺巧妙的。其實,替換掉JBuilder生成的exe檔案末尾的jar檔案就可以生成你自己的打包exe檔案。
下面程式碼是csdn blog 上fita的,原文在:http://blog.csdn.net/fita/archive/2005/03/23/327838.aspx ,不過有編譯錯誤(估計是fita故意的),我只是調了調。
另一個問題是,如果是Java GUI程式,須在啟動Java程式後,開始一個訊息迴圈,否則Java程式視窗會一閃而過。
#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=./startup.jar;./DirectMail.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/qzsoft/directmail/MainFrame";
//啟動方法,通常是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;
}
#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=./startup.jar;./DirectMail.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/qzsoft/directmail/MainFrame";
//啟動方法,通常是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;
}
相關文章
- 在vmare中建立centos虛擬機器CentOS虛擬機
- 在 Fedora 中使用 Cockpit 建立虛擬機器KPI虛擬機
- 在CentOS上建立虛擬機器以及RedisCentOS虛擬機Redis
- Dalvik虛擬機器、Java虛擬機器與ART虛擬機器虛擬機Java
- java虛擬機器和Dalvik虛擬機器Java虛擬機
- Android 虛擬機器 Vs Java 虛擬機器Android虛擬機Java
- 手動在虛擬機器之間建立信任虛擬機
- 使用 Cockpit 建立虛擬機器KPI虛擬機
- 建立新的虛擬機器虛擬機
- 深入學習Java虛擬機器——虛擬機器位元組碼執行引擎Java虛擬機
- 在虛擬機器中安裝ftp虛擬機FTP
- Java虛擬機器(JVM)Java虛擬機JVM
- java~graalVM虛擬機器JavaLVM虛擬機
- kvm純命令建立虛擬機器虛擬機
- VMware Workstation Pro建立虛擬機器虛擬機
- 在虛擬機器CentOS中安裝docker虛擬機CentOSDocker
- 深入理解Java虛擬機器(程式編譯與程式碼優化)Java虛擬機編譯優化
- 在Java虛擬機器中,字串常量到底存放在哪Java虛擬機字串
- 動手實現程式碼虛擬機器虛擬機
- Java 虛擬機器之三:Java虛擬機器的記憶體結構Java虛擬機記憶體
- Java虛擬機器16:MetaspaceJava虛擬機
- 備戰- Java虛擬機器Java虛擬機
- Hyper-V批次建立虛擬機器虛擬機
- ida 在虛擬機器中實現linuxremote debugging虛擬機LinuxREM
- Java虛擬機器(二)物件的建立與OOP-Klass模型Java虛擬機物件OOP模型
- Java基礎:Java虛擬機器(JVM)Java虛擬機JVM
- 詳解Java 虛擬機器(第②篇)——HotSpot 虛擬機器物件Java虛擬機HotSpot物件
- java虛擬機器指令常量部分Java虛擬機
- 深入理解java虛擬機器Java虛擬機
- Java 虛擬機器診斷利器Java虛擬機
- Java虛擬機器是什麼?Java虛擬機
- 效率工具 | 快速建立虛擬機器,Vagrant真香!虛擬機
- JVM 系列(1) — 虛擬機器在執行期對程式碼的優化策略JVM虛擬機優化
- 虛擬化技術之kvm虛擬機器建立工具virt-install虛擬機
- 虛擬化技術之kvm虛擬機器建立工具qemu-kvm虛擬機
- Java JVM——5.Java虛擬機器棧JavaJVM虛擬機
- Java虛擬機器04——垃圾收集器Java虛擬機
- java虛擬機器類載入機制Java虛擬機
- Java 虛擬機器類載入機制Java虛擬機