C语言程序简单模拟JVM模板解释器、JIT用到的硬编码编织技术
首先,我们调用一个普通函数的代码如下:
#include <stdio.h>
int new();
int main() {
int obj1 = new();
printf("obj1=%d\n", obj1);
return 0;
}
int new() {
return 16;
}
接着,我们借助 Clion 中 GDB 工具查看函数 new 的反汇编代码:
(gdb) disassemble /mr new
Dump of assembler code for function new:
13 int new() {
0x000055555555517f <+0>: f3 0f 1e fa endbr64
0x0000555555555183 <+4>: 55 push %rbp
0x0000555555555184 <+5>: 48 89 e5 mov %rsp,%rbp
14 return 16;
0x0000555555555187 <+8>: b8 10 00 00 00 mov $0x10,%eax
15 }
=> 0x000055555555518c <+13>: 5d pop %rbp
0x000055555555518d <+14>: c3 ret
End of assembler dump.
注意,我这里用的是C语言工程,因为 C++ 中 new 是关键字,那你可能要换个函数名。
接着,我就把汇编编译后的原始字节值存入了以下源码的 asm_code
数组中,
#include <stdio.h>
#include <sys/mman.h>
#include <unistd.h>
#include <memory.h>
int new();
int template_new();
int main() {
int obj1 = new();
int obj2 = template_new();
printf("obj1=%d\n", obj1);
printf("obj2=%d\n", obj2);
return 0;
}
int new() {
return 16;
}
int template_new() {
typedef int (*p_fun)();
char asm_code[] = {
0x55,
0x48, 0x89, 0xe5,
0xb8, 0x10, 0x00, 0x00, 0x00,
0x5d,
0xc3
};
void* temp = mmap(NULL, // 映射区的开始地址,设置NULL或者0表示由系统决定
getpagesize(), // 申请的内存大小按照内存页对齐,这里直接调用函数获取内存页大小
PROT_READ | PROT_WRITE | PROT_EXEC, // 映射的内存区的权限,可读可写可执行
MAP_ANONYMOUS | MAP_PRIVATE, // 映射对象类型
-1,
0);
// 将函数机器码写入内存
memcpy(temp, asm_code, sizeof(asm_code));
p_fun fun = temp;
return fun();
}
asm_code 中代码还可以进一步精简。
JVM模板解释器针对的是单个字节码指令的优化;
JIT针对的是热点代码的优化;
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix