用Java实现JVM 第一章《命令行工具》

266 阅读1分钟

这是我参与8月更文挑战的第5天,活动详情查看:8月更文挑战

背景

Java虚拟机非常复杂,要想真正理解它的工作原理,最好的方式就是自己动手写一个。

本实现参考《自己动手写java 虚拟机》、《Java虚拟机规范》 、《小傅哥的相关博客》等。

jcommander介绍

       //pom文件
       <!-- 命令行参数解析器 -->
        <dependency>
            <groupId>com.beust</groupId>
            <artifactId>jcommander</artifactId>
            <version>1.72</version>
        </dependency>

更多相关命令行解析的只是请参考

jcommander.org/

JCommander 是一个非常小的 Java 框架,它使得解析命令行参数变得微不足道。您可以使用选项描述来注释字段:

class Main {
    @Parameter(names={"--length", "-l"})
    int length;
    @Parameter(names={"--pattern", "-p"})
    int pattern;

    public static void main(String ... argv) {
        Main main = new Main();
        JCommander.newBuilder()
            .addObject(main)
            .build()
            .parse(argv);
        main.run();
    }

    public void run() {
        System.out.printf("%d %d", length, pattern);
        System.out.println();
    }
}

在启动参数配置

image-20210814214625630.png

结果
512 2

代码

命令行工具

import com.beust.jcommander.JCommander;
import com.beust.jcommander.Parameter;

import java.util.List;

/**
 * @Author blackcat
 * @create 2021/8/11 13:42
 * @version: 1.0
 * @description:命令行相关参数
 */
public class Cmd {

    @Parameter(names = {"-?", "-help"}, description = "print help message", help = true)
    boolean helpFlag = false;

    @Parameter(names = "-version", description = "print version and exit")
    boolean versionFlag = false;

    @Parameter(names = {"-cp", "-classpath"}, description = "classpath")
    String classpath;

    @Parameter(names = "-Xjre", description = "path to jre")
    String jre;

    @Parameter(description = "main class and args")
    List<String> mainClassAndArgs;

    boolean ok;

    String getMainClass() {
        return mainClassAndArgs != null && !mainClassAndArgs.isEmpty()
                ? mainClassAndArgs.get(0)
                : null;
    }

    List<String> getAppArgs() {
        return mainClassAndArgs != null && mainClassAndArgs.size() > 1
                ? mainClassAndArgs.subList(1, mainClassAndArgs.size())
                : null;
    }

    public  static Cmd parse(String[] argv) {
        Cmd cmd = new Cmd();
        try {
            JCommander.newBuilder().addObject(cmd).args(argv).build();
            cmd.ok = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return cmd;
    }
}

测试代码

/**
 * @Author blackcat
 * @create 2021/8/11 14:08
 * @version: 1.0
 * @description:
 */
public class Main {

    public static void main(String[] args) {
        String[] argv = {"-Xjre" ,"D:\\tools\\Jdk1.8\\jre","-classpath","MainTest","MainTest","agr1","agr2"};
        Cmd cmd = Cmd.parse(argv);
        if (!cmd.ok || cmd.helpFlag) {
            System.out.println("Usage: <main class> [-options] class [args...]");
            return;
        }
        if (cmd.versionFlag) {
            System.out.println("java version \"1.8.0\"");
            return;
        }
        startJVM(cmd);
    }

    private static void startJVM(Cmd cmd) {
        System.out.printf("classpath:%s class:%s args:%s\n", cmd.classpath, cmd.getMainClass(), cmd.getAppArgs());
    }
}
//classpath:MainTest class:MainTest args:[agr1, agr2]

gitee地址

gitee.com/feicc/jjvm/…