详尽分享通过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

相关文章
|
9月前
|
NoSQL MongoDB 微服务
微服务——MongoDB实战演练——文章微服务模块搭建
本节介绍文章微服务模块的搭建过程,主要包括以下步骤:(1)创建项目工程 *article*,并在 *pom.xml* 中引入依赖;(2)配置 *application.yml* 文件;(3)创建启动类 *cn.itcast.article.ArticleApplication*;(4)启动项目,确保控制台无错误提示。通过以上步骤,完成文章微服务模块的基础构建与验证。
127 0
|
存储 缓存 JavaScript
提升Blazor应用性能的探索之旅:深入解析关键技巧与最佳实践
【8月更文挑战第31天】在开发现代Web应用时,性能与用户体验至关重要。Blazor作为一款使用.NET构建交互式Web UI的框架,提供了诸多便利。为了充分发挥其潜力并优化体验,掌握一些性能提升技巧十分必要。本文将分享几个实用的Blazor性能优化方法,包括减少不必要的服务器端调用、使用懒加载以及优化DOM操作。通过这些技巧,可以显著提升应用性能,为用户提供更流畅的体验。以下是具体方法及示例代码。
314 0
|
人工智能 自动驾驶 程序员
来重庆工作2年,想念广东了
今年中秋,我在重庆独自规划副业训练营,感到十分满足。过去五年,我从广东的一名法律研究生转型为程序员,并在自媒体领域取得一定成就。尽管过程中遇到挑战,但我现在已能通过自媒体覆盖房贷车贷,重新找回了初心与满足感。目前运营两个系列账号,分别专注于Python自动化办公和职场副业经验分享。
215 17
来重庆工作2年,想念广东了
|
存储 关系型数据库 Linux
在CentOS 7上安装和使用Docker的方法
在CentOS 7上安装和使用Docker的方法
1397 1
|
数据采集 数据挖掘 数据处理
如何用pandas处理数据集?
如何用pandas处理数据集?【7月更文挑战第8天】
195 0
|
JSON 安全 JavaScript
利用Webhook绕过支付请求
在深入了解漏洞奖励计划中的安全漏洞时,我们往往需要寻找一些用户不可见的功能下手。支付Webhook就是一种典型例子,像Stripe或Braintree这样的支付服务提供商都会使用这种技术来将用户的订购细节告知网站。重要的是,用户根本不会跟这些Webhook节点进行交互,所有的通信都是在支付提供商和服务器之间完成的。这也就意味着,很多漏洞Hunter可能从来都不会想到要去测试Webhook功能,这也就会错过很多潜在的高危漏洞。
|
运维 关系型数据库 MySQL
Linux运维工程师面试题(5)
Linux运维工程师面试题(5)1 SELECT 语句处理的顺序 2 MySQL 高可用方案有哪些 3 mysql 主从复制原理 4 mycat 读写分离原理 5 MHA 高可用原理 6 mysqldump 备份的原理 7 drop, delete 与 truncate 的区别,哪个最快 8 判断主从延迟的方法 9 MySQL 主要的索引类型 10 MySQL 中 myisam 与 innodb 的区别
238 1
|
数据采集 数据可视化 前端开发
BI图表可视化编辑器设计
本文为《浅谈BI系统设计》第3篇原创文章。在前几篇文章我们对BI系统有全局了解,后续将逐一讲解核心模块设计原理及功能实现。 接下来讲解可视化图表部分,本篇文章三个角度来说 数据可视化原理 BI中的图表可视化 图表编辑器的设计
732 1
|
Web App开发 关系型数据库 PostgreSQL
|
编解码 运维 测试技术
一文搞懂App测试,APP测试方案
一文搞懂App测试,APP测试方案
1332 0