通过exe启动class
生活随笔
收集整理的這篇文章主要介紹了
通过exe启动class
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
通過exe啟動class 昨天下載了號稱純java版的網游《海天英雄傳》, 發現其將包括jvm.dll在內的所有組件及所有class全部封裝使用,覺得這種方式比較可行,既保證了理論上的純java開發,又避免了核心代碼被反編譯的風險;于是自己也嘗試著寫了點類似方法,摘錄其中一個直接以exe文件調用main函數的發表。
本方法通過jni方式實現。
/**
?* 直接通過exe啟動class(免外部配置)
?*
?* project:loonframework
?* author:chenpeng
?* email:ceponline@yahoo.com.cn
?*/
// PS:好長時間不寫C/C++,已然快不會用了,順便復習一下……有錯大家提,大家幫忙優化……
#include "stdafx.h"
#include "jni.h"
//用于提示框顯示
void MessageBox(LPCTSTR text);
//用于路徑過濾
char* DirPath(char * path);
//MessageBox標題名稱。
static const char MessageBoxTitle[] = "Loonframework提供";???
//本程序默認的jvm.dll相對路徑位置。
const static char _DEFAULT_JVM[]="//jre//bin//client//jvm.dll";??
//主函數名,也可改為其他名稱,JVM以此查詢啟動接口。
const char MainName[] ="main";
//虛擬機啟動參數總數。
const int JVMOptionCount = 5;
//JVM編譯器設定,none為使用默認編譯器。
static char Compiler[] = "-Djava.compiler=NONE";
//最小內存
static char MinMB[] = "-Xms256M";
//最大內存
static char MaxMB[] = "-Xmx512M";
//jar包中主函數class所在路徑。
static char AppClass[] = "org/loon/framework/game/Main";???????
//需要執行的jar包所在路徑,'./'為當前路徑簡寫,多jar包以';'分割。
static char ClassPath[] = "-Djava.class.path=./loonlangrisser0.01.jar";??
static char LibraryPath[] = "-Djava.library.path=./";???????????????????????
typedef jint (WINAPI* JNICreateJavaVM)(JavaVM**, JNIEnv**, void *);
/**
?* Win主函數
?**/
int APIENTRY WinMain(HINSTANCE hInstance,
???????????????????? HINSTANCE hPrevInstance,
???????????????????? LPTSTR??? lpCmdLine,
???????????????????? int?????? nCmdShow)
{
?
??? //JVM路徑(PS:本寫法不支持中文路徑)。
??? char JVMPath[MAX_PATH];
??? /**
??? ?*本程序通過注冊表查找JVM.DLL位置。如未注冊安裝虛擬機,本程序將在執行文件相對路徑下直接獲得。)
??? ?*/
??? //設定空間大小
??? char SubKey[MAX_PATH * 2];
??? //將注冊表路徑字符串拷貝到SubKey
??? lstrcpy(SubKey, "Software//JavaSoft//Java Runtime Environment");
??? HKEY hk;
??? //查詢注冊表,并返回結果
??? LONG result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, SubKey, 0, KEY_READ, &hk);
??? //承載JVM.DLL句柄
??? HMODULE JVM_DLL;
??? //當注冊表中不存在Software//JavaSoft//Java Runtime Environment時,則從本地讀取JVM.DLL
??? if (result != ERROR_SUCCESS) {
??? ??? ? //PS:此處用于從本地路徑直接獲得JVM.DLL時的其他處理。
??? ??? ? //獲得文件所在絕對路徑,PathLength為返回的路徑長度
??? ??? ?? int PathLength = GetModuleFileName(NULL, JVMPath, MAX_PATH);
??? ??? ?? //拼裝實際路徑
??? ??? ?? lstrcat(DirPath(JVMPath),_DEFAULT_JVM);
??????? //MessageBox("Software//JavaSoft//Java Runtime Environment不存在!");
?????? // return -1;
??? //注冊表中已存在時
??? }else{
??? ??? char feedback[MAX_PATH];
??? ??? //獲得空間大小
??? ??? DWORD feedback_Length = sizeof(feedback) * sizeof(feedback[0]);
??? ??? result = RegQueryValueEx(hk, "CurrentVersion", NULL, NULL, (LPBYTE)feedback, &feedback_Length);
??? ??? //關閉注冊表
??? ??? RegCloseKey(hk);
??? ??? if (result != ERROR_SUCCESS) {
??? ??? ??? MessageBox("Software//JavaSoft//Java Runtime Environment中CurrentVersion讀取失敗!");
??? ??? ??? return -1;
??? ??? }
??? ??? //獲得路徑(lstrcat用于將第二個串和第一個連起來賦值給第一個字符串)
??? ??? lstrcat(SubKey, "//");
??? ??? lstrcat(SubKey, feedback);
??? ??? //查詢注冊表
??? ??? result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, SubKey, 0, KEY_READ, &hk);
??? ??? if (result != ERROR_SUCCESS) {
??? ??? ??? lstrcat(SubKey, "未找到!");
??? ??? ??? MessageBox(SubKey);
??? ??? ??? return -1;
??? ??? }
??? ??? feedback_Length = sizeof(feedback) * sizeof(feedback[0]);
??? ??? result = RegQueryValueEx(hk, "RuntimeLib", NULL, NULL, (LPBYTE)feedback, &feedback_Length);
??? ??? RegCloseKey(hk);
??? ??? if (result != ERROR_SUCCESS) {
??? ??? ??? lstrcat(SubKey, "Runtime Lib讀取失敗!");
??? ??? ??? MessageBox(SubKey);
??? ??? ??? return -1;
??? ??? }
??????? //獲得JVM.DLL路徑?
??? ??? lstrcpy(JVMPath, feedback);
??? }
??? ??? //獲得JVM.DLL啟動實體
??? ??? JVM_DLL = LoadLibrary(JVMPath);
??? ??? if (JVM_DLL == NULL) {
??? ??? ??? lstrcpy(SubKey, JVMPath);
??? ??? ??? lstrcat(SubKey, "載入失敗!");
??? ??? ??? MessageBox(SubKey);
??? ??? ??? return -1;
??? ??? }
??? //JVM內部函數JNI_CreateJavaVM讀取
??? JNICreateJavaVM createJavaVM = (JNICreateJavaVM)GetProcAddress(JVM_DLL, "JNI_CreateJavaVM");
??? if (createJavaVM == NULL) {
??????? MessageBox("JNI_CreateJavaVM函數讀取失敗!");
??????? return -1;
??? }
??? //指向本地方法調用接口
??? JNIEnv* env;
??? //表示Java虛擬機
??? JavaVM* jvm;
??? //設定JVM啟動參數
??? JavaVMInitArgs vm_args;
??? JavaVMOption options[JVMOptionCount];
??? ?/**
??? ? *jtl(Java Tools Language)設定:JVM的缺省行為是用“即時”編譯器(或JIT[字節代碼編譯器])執行字節碼。
??? ? *當加載類時,JIT將類字節碼轉換成本機代碼。使用JIT會導致在每個類加載后有短暫延遲,
??? ? *但可提高程序的總體性能。在某些情況下,執行時間可縮短十分之一。
??? ? *可用Compiler指定jtl,如將Compiler=foo后,該例中虛擬機將查找名為foo.dll的JIT編譯器。
??? ? *搜索其它編譯器是在jre/bin目錄中和系統的PATH上進行的。
??? ? *若找不到這樣的編譯器,虛擬機將缺省使用解釋器。
??? ? */
??? ? options[0].optionString = Compiler;??
??? ?? //類地址
????? options[1].optionString = ClassPath;??????
??? ? //lib地址
????? options[2].optionString = LibraryPath;
??? ? //最小內存
??? ? options[3].optionString = MinMB;
??? ? //最大內存
??? ? options[4].optionString = MaxMB;
??? ? //PS:此參數用于設定跟蹤運行時的信息,暫不需要。
????? //options[3].optionString = "-verbose:jni";?
??? ? //使用的jni版本,目前最高為JNI_VERSION_1_6。
????? vm_args.version? = JNI_VERSION_1_4;
????? vm_args.options? = options;
????? vm_args.nOptions = JVMOptionCount;
????? vm_args.ignoreUnrecognized = JNI_TRUE;
??? //啟動JVM,并返回結果
??? int res = createJavaVM(&jvm, &env, &vm_args);
??? if (res < 0) {
??????? MessageBox("JVM啟動失敗!");
??????? return -1;
??? }
??? //查找目的類
??? jclass clazz = env->FindClass(AppClass);
??? if (clazz == 0) {
??????? lstrcpy(SubKey, AppClass);
??????? lstrcat(SubKey, "類沒有找到!");
??????? MessageBox(SubKey);
??????? return -1;
??? }
??? //取得入口主函數序列號
??? jmethodID mid = env->GetStaticMethodID(clazz, MainName, "([Ljava/lang/String;)V");
??? if (mid == 0) {
??????? lstrcpy(SubKey, AppClass);
??????? lstrcat(SubKey, "沒有找到主函數!");
??????? MessageBox(SubKey);
??????? return -1;
??? }
??? //main啟動
??? env->CallStaticVoidMethod(clazz, mid, NULL);
??? //JVM釋放
??? jvm->DestroyJavaVM();
??? return 0;
}
/**
?* 提示框,封裝原有MessageBox
?*/
void MessageBox(LPCTSTR text) {
??? MessageBox(NULL, text, MessageBoxTitle, MB_ICONEXCLAMATION | MB_APPLMODAL | MB_OK | MB_SETFOREGROUND);
}
/**
?* 過濾文件所在絕對路徑,去掉最后'/'后字符。
?*/
char* DirPath(char * path)
{
?char *ph = path;
?char *tag = ph;
?while (*ph)
?{
? if ( (*ph) == '//' )
?? tag = ph;
?? ++ph;
?}
?*tag = '/0';
?return path;
}
運行效果圖如下:
源碼如下,請該后綴為.rar
posted on 2007-10-27 11:53 cping 閱讀(...) 評論(...) 編輯 收藏
本方法通過jni方式實現。
/**
?* 直接通過exe啟動class(免外部配置)
?*
?* project:loonframework
?* author:chenpeng
?* email:ceponline@yahoo.com.cn
?*/
// PS:好長時間不寫C/C++,已然快不會用了,順便復習一下……有錯大家提,大家幫忙優化……
#include "stdafx.h"
#include "jni.h"
//用于提示框顯示
void MessageBox(LPCTSTR text);
//用于路徑過濾
char* DirPath(char * path);
//MessageBox標題名稱。
static const char MessageBoxTitle[] = "Loonframework提供";???
//本程序默認的jvm.dll相對路徑位置。
const static char _DEFAULT_JVM[]="//jre//bin//client//jvm.dll";??
//主函數名,也可改為其他名稱,JVM以此查詢啟動接口。
const char MainName[] ="main";
//虛擬機啟動參數總數。
const int JVMOptionCount = 5;
//JVM編譯器設定,none為使用默認編譯器。
static char Compiler[] = "-Djava.compiler=NONE";
//最小內存
static char MinMB[] = "-Xms256M";
//最大內存
static char MaxMB[] = "-Xmx512M";
//jar包中主函數class所在路徑。
static char AppClass[] = "org/loon/framework/game/Main";???????
//需要執行的jar包所在路徑,'./'為當前路徑簡寫,多jar包以';'分割。
static char ClassPath[] = "-Djava.class.path=./loonlangrisser0.01.jar";??
static char LibraryPath[] = "-Djava.library.path=./";???????????????????????
typedef jint (WINAPI* JNICreateJavaVM)(JavaVM**, JNIEnv**, void *);
/**
?* Win主函數
?**/
int APIENTRY WinMain(HINSTANCE hInstance,
???????????????????? HINSTANCE hPrevInstance,
???????????????????? LPTSTR??? lpCmdLine,
???????????????????? int?????? nCmdShow)
{
?
??? //JVM路徑(PS:本寫法不支持中文路徑)。
??? char JVMPath[MAX_PATH];
??? /**
??? ?*本程序通過注冊表查找JVM.DLL位置。如未注冊安裝虛擬機,本程序將在執行文件相對路徑下直接獲得。)
??? ?*/
??? //設定空間大小
??? char SubKey[MAX_PATH * 2];
??? //將注冊表路徑字符串拷貝到SubKey
??? lstrcpy(SubKey, "Software//JavaSoft//Java Runtime Environment");
??? HKEY hk;
??? //查詢注冊表,并返回結果
??? LONG result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, SubKey, 0, KEY_READ, &hk);
??? //承載JVM.DLL句柄
??? HMODULE JVM_DLL;
??? //當注冊表中不存在Software//JavaSoft//Java Runtime Environment時,則從本地讀取JVM.DLL
??? if (result != ERROR_SUCCESS) {
??? ??? ? //PS:此處用于從本地路徑直接獲得JVM.DLL時的其他處理。
??? ??? ? //獲得文件所在絕對路徑,PathLength為返回的路徑長度
??? ??? ?? int PathLength = GetModuleFileName(NULL, JVMPath, MAX_PATH);
??? ??? ?? //拼裝實際路徑
??? ??? ?? lstrcat(DirPath(JVMPath),_DEFAULT_JVM);
??????? //MessageBox("Software//JavaSoft//Java Runtime Environment不存在!");
?????? // return -1;
??? //注冊表中已存在時
??? }else{
??? ??? char feedback[MAX_PATH];
??? ??? //獲得空間大小
??? ??? DWORD feedback_Length = sizeof(feedback) * sizeof(feedback[0]);
??? ??? result = RegQueryValueEx(hk, "CurrentVersion", NULL, NULL, (LPBYTE)feedback, &feedback_Length);
??? ??? //關閉注冊表
??? ??? RegCloseKey(hk);
??? ??? if (result != ERROR_SUCCESS) {
??? ??? ??? MessageBox("Software//JavaSoft//Java Runtime Environment中CurrentVersion讀取失敗!");
??? ??? ??? return -1;
??? ??? }
??? ??? //獲得路徑(lstrcat用于將第二個串和第一個連起來賦值給第一個字符串)
??? ??? lstrcat(SubKey, "//");
??? ??? lstrcat(SubKey, feedback);
??? ??? //查詢注冊表
??? ??? result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, SubKey, 0, KEY_READ, &hk);
??? ??? if (result != ERROR_SUCCESS) {
??? ??? ??? lstrcat(SubKey, "未找到!");
??? ??? ??? MessageBox(SubKey);
??? ??? ??? return -1;
??? ??? }
??? ??? feedback_Length = sizeof(feedback) * sizeof(feedback[0]);
??? ??? result = RegQueryValueEx(hk, "RuntimeLib", NULL, NULL, (LPBYTE)feedback, &feedback_Length);
??? ??? RegCloseKey(hk);
??? ??? if (result != ERROR_SUCCESS) {
??? ??? ??? lstrcat(SubKey, "Runtime Lib讀取失敗!");
??? ??? ??? MessageBox(SubKey);
??? ??? ??? return -1;
??? ??? }
??????? //獲得JVM.DLL路徑?
??? ??? lstrcpy(JVMPath, feedback);
??? }
??? ??? //獲得JVM.DLL啟動實體
??? ??? JVM_DLL = LoadLibrary(JVMPath);
??? ??? if (JVM_DLL == NULL) {
??? ??? ??? lstrcpy(SubKey, JVMPath);
??? ??? ??? lstrcat(SubKey, "載入失敗!");
??? ??? ??? MessageBox(SubKey);
??? ??? ??? return -1;
??? ??? }
??? //JVM內部函數JNI_CreateJavaVM讀取
??? JNICreateJavaVM createJavaVM = (JNICreateJavaVM)GetProcAddress(JVM_DLL, "JNI_CreateJavaVM");
??? if (createJavaVM == NULL) {
??????? MessageBox("JNI_CreateJavaVM函數讀取失敗!");
??????? return -1;
??? }
??? //指向本地方法調用接口
??? JNIEnv* env;
??? //表示Java虛擬機
??? JavaVM* jvm;
??? //設定JVM啟動參數
??? JavaVMInitArgs vm_args;
??? JavaVMOption options[JVMOptionCount];
??? ?/**
??? ? *jtl(Java Tools Language)設定:JVM的缺省行為是用“即時”編譯器(或JIT[字節代碼編譯器])執行字節碼。
??? ? *當加載類時,JIT將類字節碼轉換成本機代碼。使用JIT會導致在每個類加載后有短暫延遲,
??? ? *但可提高程序的總體性能。在某些情況下,執行時間可縮短十分之一。
??? ? *可用Compiler指定jtl,如將Compiler=foo后,該例中虛擬機將查找名為foo.dll的JIT編譯器。
??? ? *搜索其它編譯器是在jre/bin目錄中和系統的PATH上進行的。
??? ? *若找不到這樣的編譯器,虛擬機將缺省使用解釋器。
??? ? */
??? ? options[0].optionString = Compiler;??
??? ?? //類地址
????? options[1].optionString = ClassPath;??????
??? ? //lib地址
????? options[2].optionString = LibraryPath;
??? ? //最小內存
??? ? options[3].optionString = MinMB;
??? ? //最大內存
??? ? options[4].optionString = MaxMB;
??? ? //PS:此參數用于設定跟蹤運行時的信息,暫不需要。
????? //options[3].optionString = "-verbose:jni";?
??? ? //使用的jni版本,目前最高為JNI_VERSION_1_6。
????? vm_args.version? = JNI_VERSION_1_4;
????? vm_args.options? = options;
????? vm_args.nOptions = JVMOptionCount;
????? vm_args.ignoreUnrecognized = JNI_TRUE;
??? //啟動JVM,并返回結果
??? int res = createJavaVM(&jvm, &env, &vm_args);
??? if (res < 0) {
??????? MessageBox("JVM啟動失敗!");
??????? return -1;
??? }
??? //查找目的類
??? jclass clazz = env->FindClass(AppClass);
??? if (clazz == 0) {
??????? lstrcpy(SubKey, AppClass);
??????? lstrcat(SubKey, "類沒有找到!");
??????? MessageBox(SubKey);
??????? return -1;
??? }
??? //取得入口主函數序列號
??? jmethodID mid = env->GetStaticMethodID(clazz, MainName, "([Ljava/lang/String;)V");
??? if (mid == 0) {
??????? lstrcpy(SubKey, AppClass);
??????? lstrcat(SubKey, "沒有找到主函數!");
??????? MessageBox(SubKey);
??????? return -1;
??? }
??? //main啟動
??? env->CallStaticVoidMethod(clazz, mid, NULL);
??? //JVM釋放
??? jvm->DestroyJavaVM();
??? return 0;
}
/**
?* 提示框,封裝原有MessageBox
?*/
void MessageBox(LPCTSTR text) {
??? MessageBox(NULL, text, MessageBoxTitle, MB_ICONEXCLAMATION | MB_APPLMODAL | MB_OK | MB_SETFOREGROUND);
}
/**
?* 過濾文件所在絕對路徑,去掉最后'/'后字符。
?*/
char* DirPath(char * path)
{
?char *ph = path;
?char *tag = ph;
?while (*ph)
?{
? if ( (*ph) == '//' )
?? tag = ph;
?? ++ph;
?}
?*tag = '/0';
?return path;
}
運行效果圖如下:
源碼如下,請該后綴為.rar
posted on 2007-10-27 11:53 cping 閱讀(...) 評論(...) 編輯 收藏
轉載于:https://www.cnblogs.com/cping1982/archive/2007/10/27/2258098.html
總結
以上是生活随笔為你收集整理的通过exe启动class的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ORACLE的索引和约束详解
- 下一篇: 微软计划2008年初发布Windows