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