详尽分享通过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编译器。

//代码效果参考:http://www.zidongmutanji.com/bxxx/487882.html

搜索其它编译器是在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 //代码效果参考:http://www.zidongmutanji.com/zsjx/106065.html

= 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

相关文章
|
7月前
|
安全 Windows
安装MyEclipse遇到错误提示 Failed to find a Main Class in “C:Windows\Temp\“时的解决方案
安装MyEclipse遇到错误提示 Failed to find a Main Class in “C:Windows\Temp\“时的解决方案
106 1
|
2月前
|
应用服务中间件 Shell PHP
thinkphp 设置运行目录为/public后 404错误
thinkphp 设置运行目录为/public后 404错误
|
6月前
|
Java 编译器 C++
详尽分享通过exe启动class
详尽分享通过exe启动class
33 0
|
6月前
|
自然语言处理 C# 图形学
​一款开源的.NET程序集反编译、编辑和调试神器
本文介绍了.NET反编译和调试工具dnSpyEx的使用方法。dnSpyEx是dnSpy的非官方Fork版本,支持.NET Framework、.NET Core和Unity程序集的调试和编辑,具有多种语言界面。主要功能包括:浅色、蓝色和深色主题,调试支持,代码编辑以及多语言支持。用户可以从GitHub下载并直接运行dnSpyEx,无需安装。通过创建测试项目,编译成dll文件,然后使用dnSpyEx进行调试和编辑程序集中的代码和IL指令。此外,文章还提供了项目源码地址和相关优秀项目的链接。
130 0
|
7月前
|
Java
Java【付诸实践 04】Jar包class文件反编译、修改、重新编译打包方法(含反编译工具jd-gui-windows-1.6.6.zip百度云资源)
Java【付诸实践 04】Jar包class文件反编译、修改、重新编译打包方法(含反编译工具jd-gui-windows-1.6.6.zip百度云资源)
832 0
|
Android开发
Android项目中运行main方法,进行测试,配置方法
Android项目中运行main方法,进行测试,配置方法
358 1
「SharpC2学习」EXE载荷生成流程
「SharpC2学习」EXE载荷生成流程
调试实战 —— dll 加载失败之 Debug Release 争锋篇
调试实战 —— dll 加载失败之 Debug Release 争锋篇
|
测试技术
loadrunner入门教程(6) --新建脚本
新建脚本及一些注意的事项
109 0
loadrunner入门教程(6) --新建脚本
|
C# C++ Windows
C#编程-92:ILDasm启动方法
C#编程-92:ILDasm启动方法
C#编程-92:ILDasm启动方法