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

相关文章
|
存储 Prometheus Kubernetes
OpenTelemetry 简析
OpenTelemetry 是 CNCF 的一个可观测性项目,旨在提供可观测性领域的标准化方案,解决观测数据的数据模型、采集、处理、导出等的标准化问题,提供与三方 vendor 无关的服务。 2021.02.10,OpenTelemetry 的 tracing spec 达到 1.0 版本 (link),基于这个里程碑,笔者对 OpenTelemetry 进行了探索,判断在可观测性领域带来的价值和发展前景。 下面给出笔者对 OpenTelemetry 的理解,抛砖引玉。由于笔者能力有限,理解不当的地方请大家指正。
OpenTelemetry 简析
|
网络架构 网络协议
|
11月前
|
运维 Prometheus 数据可视化
如何一键接入opentelemetry项目,实现可观测分析
本文揭秘如何通过Databuff实现OpenTelemetry的无缝接管,无需改造现有Collector,10分钟完成部署,实现服务与资源间的因果可观测性,呈现云网空间地图,助力运维智能化。
|
9月前
|
人工智能 缓存 运维
2026年阿里云上OpenClaw从0到1搭建多 Agent 团队协作系统实战指南,执行效率提升10倍以上
在AI工具从“单点能力”向“系统协作”进化的今天,OpenClaw多Agent系统凭借“分工协作、自动拆解、实时联动”的核心优势,彻底改变了AI的使用逻辑——它不再是单打独斗的工具,而是能组成“数字战队”的协作系统,让复杂任务的执行效率提升10倍以上。
3496 8
|
8月前
|
人工智能 API 决策智能
保姆级图文教程!OpenClaw零基础阿里云/本地部署配置免费大模型API+ClawPort多Agent管控及常见问题解答
2026年,AI Agent的规模化应用已从“单点尝试”走向“团队协作”,越来越多用户开始同时管理5个以上OpenClaw(曾用名Clawdbot)智能体,构建专属的“AI军团”——编排器负责任务拆解、研究员专注资料搜集、写作者产出内容、SEO专家优化传播……但随之而来的管理难题让不少用户陷入混乱:终端标签页疯狂切换、智能体上下文互不共享、任务进度追踪困难、Token成本不透明、定时任务失控。
1511 4
|
8月前
|
人工智能 机器人 网络安全
OpenClaw 多机器人阿里云+本地部署实战教程,+Telegram多Gateway+多Bot架构搭建分工明确 AI 小团队
把OpenClaw当作单一聊天框使用,迟早会陷入“上下文污染、模型切换频繁、任务互相抢占”的困境——让写文案的Agent聊技术,让查资讯的Agent写代码,最后变成“万能但不靠谱”的杂物堆。真正高效的用法是将其拆分为“专业小队”:用多个Telegram Bot作为入口,搭配多OpenClaw Gateway隔离运行,每个Bot对应一个专项Agent,私聊不同Bot即可切换“专业助手”,无需手动输入命令切换身份。
1591 2
|
8月前
|
存储 自然语言处理 机器人
OpenClaw 搭团队太折腾?这个 Skill 一键搞定多智能体协作
阿里云OpenClaw是专为多智能体协作设计的基座,采用Actor架构,支持Agent独立运行与消息驱动协作。针对协作规范缺失、配置复杂、过程不透明等痛点,推出agentrun-team Skill,实现“一句话建团队、自然语言下任务”,让智能体像真实员工一样高效协同。
|
Go API 开发工具
Opentelemetry SDK的简单用法
Opentelemetry SDK的简单用法
468 3
|
9月前
|
人工智能 负载均衡 前端开发
2026年OpenClaw/Clawdbot多Agent实战指南:阿里云极速搭建,“1个人=1支高效AI团队”
在AI自动化深度落地的2026年,单一智能体的“全能模式”早已无法适配复杂的工作场景——记忆臃肿引发的响应迟缓、多任务并行导致的上下文污染、无关信息加载造成的Token大量浪费,这些痛点让OpenClaw(原Clawdbot)的技术潜力难以充分释放。而**多Agent架构**的出现,彻底打破了这一桎梏,通过“单Gateway+多分身”的创新模式,让一个智能机器人能在不同场景下切换独立“大脑”,如同组建起一支分工明确的AI团队,实现创意策划、内容写作、代码开发、数据分析等任务的高效协同,真正做到“一个人=一支高效军团”。
2701 2

热门文章

最新文章