尝试写一个jvm吧

为啥要尝试写一个呢,自从工作后,感觉就很少接触github了,也没精力去玩啥开源了,但自己还是喜欢学习其他东西,可能多动症???

尝试写一个jvm吧,本次选用语言是rust。

其实我个人也是rust初学者,到现在,仍然只是会一些简单语法,对于其宏、多线程仍然是跨不过去的门槛,所以本次 只会用一些基础语法来进行开发,目前应该java coder和go coder比较多,我本人也是一个java coder,所以这篇文章,仍然是以java coder能够看懂的情况下来开发。

墨滴链接:【https://mdnice.com/writing/60f896096b4a4f6aa55aee6ab8ce4f35】

公众号:Azhs的技术小屋(https://mp.weixin.qq.com/s/PTxS_1nnKdYy1Pz6aB0Abg)

目前准备分为这么几个部分:

  1. command line processing
  2. find class file
  3. parse class file
  4. implements runtime_data
  5. instruction set and interpreter
  6. heap and object
  7. method invoke
  8. array and string
  9. native
  10. exception
  11. ...

大概这么几个步骤,可能没有看到GC,我这儿想说的是,选rust的原因就在于它是一门无GC语言,当然如果想模仿一下也是可以,无非就是自己实现一套buffer的申请和回收,这个可以考虑,简单实现难度不大,如果加入动态GC、安全点啥的就挺有难度了,后面再说趴~

最后要说的就是我估计进度会很慢,毕竟公司是真滴挺卷的,基本只有周末时间来开发一点点~

命令行处理

预期效果 我可以通过类似java -v 或者 xxx -help的方式看到一些命令, 我的二进制包叫azh, 所以命令如下

./target/debug/azh -h

./target/debug/azh -v

一、环境准备

主要是一些必备的tracing日志包、env环境等包的引入

[package]
name = "azh" # 放你自己想要的名字,build时二进制包的名字
version = "0.1.0"
edition = "2021"

[dependencies]
getopts = "0.2.21"
tracing = "0.1.37"
tracing-subscriber = "0.3.16"

二、主要开发

2.1 定义Command命令行结构体

#[derive(Debug)]
pub struct Command {
    pub help_flag: bool,  
    pub version_flag: bool,
    pub info_flag: bool,
}

其中三个属性分别对应命令的help、version、info。

2.2 实现command解析: parse_command()方法

  • 获取命令行参数
let args: Vec<String> = env::args().collect();
let program = args[0].clone();
let mut opts = Options::new();
  • 定义参数的解析方式
let opts = opts
        .parsing_style(ParsingStyle::StopAtFirstFree)
        .long_only(true);
opts.optflag("h", "help", "Print help message");
opts.optflag("v", "version", "Print version and exit");
opts.optflag("", "info", "Print info about azh-jvm");

rust是标准的函数式编程,可以在学习过程中慢慢发现它的美。 上面代码中有两个点得注意下:

ParsingStyle::StopAtFirstFree: 解析时剩余参数不作为标记参数的一部分

long_only: 为true时允许使用 -xxx

  • 对参数进行匹配
let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(err) => {
            print_introduction_message(&program, opts);
            panic!("{}", err.to_string());
        }
    };

    // 匹配help
    if matches.opt_present("help") {
        command.help_flag = true;
    }

    if matches.opt_present("version") {
        command.version_flag = true;
    }

    if matches.opt_present("info") {
        command.info_flag = true;
    }

rust是门很严格的语言,上面的match代码段就是做一个判断,如果parse错误我们要选择什么处理方式,rust的特点就是任何代码,要么success,要么就err,所以当我们考虑了所有的场景后,如果你的代码build成功,基本就不会出现线上问题。相信java coder很容易遇到npe问题(NullPointerException, 我在公司线上遇到过,一个npe 1块钱,我们并发很高,记得那天还是没有直播带货的场景,1s就出现了300来个npe... 当时就请各位同事周会喝奶茶...)

  • print_introduction_message() 方法
fn print_introduction_message(program: &str, opts: &mut Options) {
    let brief = format!("Usage: {} [-options] class [args...]", program);
    info!("{}", opts.usage(&brief));
}
impl Command {
    pub fn print_introduction_message(&self) {
        let args: Vec<String> = env::args().collect();
        info!(
            "------ Usage: {} [-options] class [args...] ------",
            args[0]
        );
    }
}

上面就基本完成了,最后你只需要

cargo build + cargo fmt 后如果没有error就构建二进制包成功了,最好也不要有waring、一个好的开发者不应该有任何一个waring出现在屏幕上。

然后通过你的二进制包,输入./xxx -h的方式就可以复现我们刚才的命令了~

#项目##求职##大厂##实习##内推#
全部评论
给个内推,目前我们组新出来两个hc,比较急,只要23届,感兴趣的投递试试
2 回复
分享
发布于 2023-03-29 12:57 北京
能用Java手写一个jvm吗😉
2 回复
分享
发布于 2023-04-25 00:47 北京
联易融
校招火热招聘中
官网直投
太强了
点赞 回复
分享
发布于 2023-03-24 21:38 福建
好牛
点赞 回复
分享
发布于 2023-03-24 23:43 北京
jvm应该比较好写,静态类型语言,而且有作业可以抄。都自己写了建议直接搞个自己顺手的新语言。
点赞 回复
分享
发布于 2023-03-25 00:44 北京
手写jvm。。。
点赞 回复
分享
发布于 2023-04-03 14:50 陕西

相关推荐

头像
昨天 15:05
已编辑
腾讯_后端开发
小红书 iOS社区技术 年薪52w+包三餐大小周
点赞 评论 收藏
转发
23 26 评论
分享
牛客网
牛客企业服务