jvm-demo 系列一:解析命令行工具类

本贴最后更新于 607 天前,其中的信息可能已经沧海桑田

参考资料:《深入理解 java 虚拟机》

《自己动手写 java 虚拟机》

zachaxy 手写 jvm 系列

先自己动手编写一个类似 java 命令行的工具,用它启动虚拟机。Java 虚拟机的工作是运行 Java 应用程序。和其他类型的应用程序一样,Java 应用程序也需要一个入口点,这个入口点就是我们熟知的 main()方法。如果一个类包含 main()方法,这个类就可以用来启动 Java 应用程序,我们把这个类叫作主类。最简单的 Java 程序是
只有一个 main()方法的类,如著名的 HelloWorld 程序。那么 Java 虚拟机如何知道我们要从哪个类启动应用程序呢?对此,Java 虚拟机规范没有明确规定。也就是说,是由虚拟机实现自行决定的。比如 Oracle 的 Java 虚拟机实现是通过 java 命令来启动的,主类名由命令行参数指定。java 命令有如下形式:

java [-options] class [args]

java [-options] -jar jarfile [args]

javaw [-options] class [args]

这里我们不先考虑完整的 java 命令用法,打算实现几个比较基础的命令

      java -version
      java -?
      java -help
      java -cp your/classpath yourClassName

先用一个结构体表示命令行

public class Cmd{
    Boolean helpFlag;//是否是help命令
    Boolean versionFlag;//是否是查看版本命令
    String cpOption;//classPath路径
    String  clazz;//
    String[]  args;//执行clazz文件需要的参数
}

先对输入的命令进行正则表达式处理,判断是否符合 java 命令用法,不符合直接返回错误。

public class CmdValidator {
    private static final Pattern CMD_PATTERN = Pattern.compile("^java\\s+(-version|-\\?|-help|-cp|-classpath)\\s*(.*)$");
     public  static  boolean isValidCmd(String cmdLine){
         Matcher matcher=CMD_PATTERN.matcher(cmdLine);
         return matcher.matches();
     }
}

一开始我是想去用 if,else 的逻辑去判断命令行处理,类似于这样

 public void parseCmd(String[] args){
       if("-help".equals(args[1]) || "-?".equals(args[1])){
           System.out.println("java help");
       }else if("-verson".equals(args[1])){
           System.out.println("java version");
       }else if("-cp".equals(args[1])){
           System.out.println("java  -cp");
           System.out.println(args[2]+"  "+args[3]);
       }

代码看起来太丑陋了,而且这种代码只是我们实现的命令少,实现的命令多就会非常冗杂,所以我们用责任链模式优化一下。

我们定义了一个抽象类 CommandHandler,它代表责任链中的一个处理步骤。每个具体的处理者类(如 HelpHandlerVersionHandlerClasspathHandler)都负责检查它是否可以处理给定的命令行参数。如果它不能处理,就将处理委托给责任链中的下一个处理者。

public abstract class CommandHandler {
    protected CommandHandler successor;

    public void setSuccessor(CommandHandler successor) {
        this.successor = successor;
    }

    public abstract void handleCommand(String[] args);
}

public class HelpHandler extends CommandHandler {
    @Override
    public void handleCommand(String[] args) {
        if ("-help".equals(args[1]) || "-?".equals(args[1])) {
            System.out.println("java help");
        } else if (successor != null) {
            successor.handleCommand(args);
        }
    }
}

public class VersionHandler extends CommandHandler {
    @Override
    public void handleCommand(String[] args) {
        if ("-version".equals(args[1])) {
            System.out.println("java version");
        } else if (successor != null) {
            successor.handleCommand(args);
        }
    }
}

public class ClassPathHandler extends CommadHandler{
    @Override
    public void handleCommand(String[] args) {
     if("-cp".equals(args[1])){
         System.out.println("successful");
         System.out.println("class文件的路径"+args[2]+"class文件"+args[3]+"交给下一节处理");
     } else if (successor != null) {
         successor.handleCommand(args);
     }
    }
}

public class Cmd {
    Boolean helpFlag;//是否是help命令
    Boolean versionFlag;//是否是查看版本命令
    String cpOption;//classPath路径
    String[]  args;//执行clazz文件需要的参数
    private CommandHandler handler;

   public  Cmd(String cmdLine){
         //解析命令行参数,以单个或者多个空格分开,这种方式目前不支持,因为如果输入的 路径名 中间有空格会导致下面解析失败
        if(!CmdValidator.isValidCmd(cmdLine)){
            System.out.println("Unrecognized option: -ewf\n" +
                    "Error: Could not create the Java Virtual Machine.\n" +
                    "Error: A fatal exception has occurred. Program will exit.");
            return;
        }
        //初始化责任链
        CommadHandler helpHandler=new HelperHandler();
        CommadHandler vesionHandler=new VersionHandler();
        CommadHandler classpathHandler=new ClassPathHandler();
        helpHandler.setSuccessor(vesionHandler);
        vesionHandler.setSuccessor(classpathHandler);
        handler=helpHandler;
        String[] args = cmdLine.trim().split("\\s+");
        parseCmd(args);
    }

    public void parseCmd(String[] args) {
        handler.handleCommand(args);
    }
}

Cmd 类中,我们初始化了责任链,然后调用 handler.handleCommand(args) 来开始处理命令行参数。

+------------------+          +------------------+
|   CommandHandler |          |     Cmd          |
+------------------+          +------------------+
| - successor      |          | - handler        |
+------------------+          +------------------+
       |                          |
       +--------------------------+
                          |
                 +------------------+
                 |  HelpHandler     |
                 +------------------+
                 |  handleCommand() |
                 +------------------+
                          |
                 +------------------+
                 |  VersionHandler  |
                 +------------------+
                 |  handleCommand() |
                 +------------------+
                          |
                 +------------------+
                 | ClasspathHandler |
                 +------------------+
                 |  handleCommand() |
                 +------------------+

这个逻辑图展示了这几个类之间的关系。CommandHandler 类是一个抽象类,它定义了一个 successor 属性,该属性表示责任链中的下一个处理者。具体的处理者类(HelpHandlerVersionHandlerClasspathHandler)继承自 CommandHandler 类,并实现了 handleCommand 方法来处理命令行参数。Cmd 类初始化了责任链,并调用责任链的第一个处理者(HelpHandler)来处理命令行参数。

责任链模式的使用让代码的扩展性变好了。

  • JVM

    JVM(Java Virtual Machine)Java 虚拟机是一个微型操作系统,有自己的硬件构架体系,还有相应的指令系统。能够识别 Java 独特的 .class 文件(字节码),能够将这些文件中的信息读取出来,使得 Java 程序只需要生成 Java 虚拟机上的字节码后就能在不同操作系统平台上进行运行。

    180 引用 • 120 回帖 • 2 关注
  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3190 引用 • 8214 回帖 • 1 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • 职场

    找到自己的位置,萌新烦恼少。

    127 引用 • 1706 回帖
  • MyBatis

    MyBatis 本是 Apache 软件基金会 的一个开源项目 iBatis,2010 年这个项目由 Apache 软件基金会迁移到了 google code,并且改名为 MyBatis ,2013 年 11 月再次迁移到了 GitHub。

    170 引用 • 414 回帖 • 387 关注
  • InfluxDB

    InfluxDB 是一个开源的没有外部依赖的时间序列数据库。适用于记录度量,事件及实时分析。

    2 引用 • 76 关注
  • C

    C 语言是一门通用计算机编程语言,应用广泛。C 语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。

    85 引用 • 165 回帖 • 2 关注
  • ReactiveX

    ReactiveX 是一个专注于异步编程与控制可观察数据(或者事件)流的 API。它组合了观察者模式,迭代器模式和函数式编程的优秀思想。

    1 引用 • 2 回帖 • 161 关注
  • Windows

    Microsoft Windows 是美国微软公司研发的一套操作系统,它问世于 1985 年,起初仅仅是 Microsoft-DOS 模拟环境,后续的系统版本由于微软不断的更新升级,不但易用,也慢慢的成为家家户户人们最喜爱的操作系统。

    223 引用 • 474 回帖
  • Notion

    Notion - The all-in-one workspace for your notes, tasks, wikis, and databases.

    7 引用 • 40 回帖
  • 安装

    你若安好,便是晴天。

    132 引用 • 1184 回帖 • 1 关注
  • Dubbo

    Dubbo 是一个分布式服务框架,致力于提供高性能和透明化的 RPC 远程服务调用方案,是 [阿里巴巴] SOA 服务化治理方案的核心框架,每天为 2,000+ 个服务提供 3,000,000,000+ 次访问量支持,并被广泛应用于阿里巴巴集团的各成员站点。

    60 引用 • 82 回帖 • 604 关注
  • frp

    frp 是一个可用于内网穿透的高性能的反向代理应用,支持 TCP、UDP、 HTTP 和 HTTPS 协议。

    20 引用 • 7 回帖 • 2 关注
  • 思源笔记

    思源笔记是一款隐私优先的个人知识管理系统,支持完全离线使用,同时也支持端到端加密同步。

    融合块、大纲和双向链接,重构你的思维。

    23003 引用 • 92509 回帖 • 2 关注
  • Webswing

    Webswing 是一个能将任何 Swing 应用通过纯 HTML5 运行在浏览器中的 Web 服务器,详细介绍请看 将 Java Swing 应用变成 Web 应用

    1 引用 • 15 回帖 • 637 关注
  • Swift

    Swift 是苹果于 2014 年 WWDC(苹果开发者大会)发布的开发语言,可与 Objective-C 共同运行于 Mac OS 和 iOS 平台,用于搭建基于苹果平台的应用程序。

    36 引用 • 37 回帖 • 535 关注
  • Q&A

    提问之前请先看《提问的智慧》,好的问题比好的答案更有价值。

    8442 引用 • 38442 回帖 • 154 关注
  • LeetCode

    LeetCode(力扣)是一个全球极客挚爱的高质量技术成长平台,想要学习和提升专业能力从这里开始,充足技术干货等你来啃,轻松拿下 Dream Offer!

    209 引用 • 72 回帖
  • 笔记

    好记性不如烂笔头。

    308 引用 • 793 回帖
  • 生活

    生活是指人类生存过程中的各项活动的总和,范畴较广,一般指为幸福的意义而存在。生活实际上是对人生的一种诠释。生活包括人类在社会中与自己息息相关的日常活动和心理影射。

    230 引用 • 1454 回帖
  • Tomcat

    Tomcat 最早是由 Sun Microsystems 开发的一个 Servlet 容器,在 1999 年被捐献给 ASF(Apache Software Foundation),隶属于 Jakarta 项目,现在已经独立为一个顶级项目。Tomcat 主要实现了 JavaEE 中的 Servlet、JSP 规范,同时也提供 HTTP 服务,是市场上非常流行的 Java Web 容器。

    162 引用 • 529 回帖 • 5 关注
  • BND

    BND(Baidu Netdisk Downloader)是一款图形界面的百度网盘不限速下载器,支持 Windows、Linux 和 Mac,详细介绍请看这里

    107 引用 • 1281 回帖 • 34 关注
  • 禅道

    禅道是一款国产的开源项目管理软件,她的核心管理思想基于敏捷方法 scrum,内置了产品管理和项目管理,同时又根据国内研发现状补充了测试管理、计划管理、发布管理、文档管理、事务管理等功能,在一个软件中就可以将软件研发中的需求、任务、bug、用例、计划、发布等要素有序的跟踪管理起来,完整地覆盖了项目管理的核心流程。

    5 引用 • 15 回帖 • 102 关注
  • Android

    Android 是一种以 Linux 为基础的开放源码操作系统,主要使用于便携设备。2005 年由 Google 收购注资,并拉拢多家制造商组成开放手机联盟开发改良,逐渐扩展到到平板电脑及其他领域上。

    334 引用 • 323 回帖 • 3 关注
  • 面试

    面试造航母,上班拧螺丝。多面试,少加班。

    325 引用 • 1395 回帖
  • Vditor

    Vditor 是一款浏览器端的 Markdown 编辑器,支持所见即所得、即时渲染(类似 Typora)和分屏预览模式。它使用 TypeScript 实现,支持原生 JavaScript、Vue、React 和 Angular。

    354 引用 • 1823 回帖 • 1 关注
  • 又拍云

    又拍云是国内领先的 CDN 服务提供商,国家工信部认证通过的“可信云”,乌云众测平台认证的“安全云”,为移动时代的创业者提供新一代的 CDN 加速服务。

    21 引用 • 37 回帖 • 548 关注
  • ngrok

    ngrok 是一个反向代理,通过在公共的端点和本地运行的 Web 服务器之间建立一个安全的通道。

    7 引用 • 63 回帖 • 627 关注
  • 自由行
    4 关注
  • 京东

    京东是中国最大的自营式电商企业,2015 年第一季度在中国自营式 B2C 电商市场的占有率为 56.3%。2014 年 5 月,京东在美国纳斯达克证券交易所正式挂牌上市(股票代码:JD),是中国第一个成功赴美上市的大型综合型电商平台,与腾讯、百度等中国互联网巨头共同跻身全球前十大互联网公司排行榜。

    14 引用 • 102 回帖 • 354 关注