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

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

参考资料:《深入理解 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 回帖
  • Java

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

    3187 引用 • 8213 回帖

相关帖子

欢迎来到这里!

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

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

推荐标签 标签

  • Git

    Git 是 Linux Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。

    209 引用 • 358 回帖
  • Mac

    Mac 是苹果公司自 1984 年起以“Macintosh”开始开发的个人消费型计算机,如:iMac、Mac mini、Macbook Air、Macbook Pro、Macbook、Mac Pro 等计算机。

    166 引用 • 595 回帖
  • API

    应用程序编程接口(Application Programming Interface)是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节。

    77 引用 • 430 回帖 • 2 关注
  • Bootstrap

    Bootstrap 是 Twitter 推出的一个用于前端开发的开源工具包。它由 Twitter 的设计师 Mark Otto 和 Jacob Thornton 合作开发,是一个 CSS / HTML 框架。

    18 引用 • 33 回帖 • 660 关注
  • PWA

    PWA(Progressive Web App)是 Google 在 2015 年提出、2016 年 6 月开始推广的项目。它结合了一系列现代 Web 技术,在网页应用中实现和原生应用相近的用户体验。

    14 引用 • 69 回帖 • 154 关注
  • PWL

    组织简介

    用爱发电 (Programming With Love) 是一个以开源精神为核心的民间开源爱好者技术组织,“用爱发电”象征开源与贡献精神,加入组织,代表你将遵守组织的“个人开源爱好者”的各项条款。申请加入:用爱发电组织邀请帖
    用爱发电组织官网:https://programmingwithlove.stackoverflow.wiki/

    用爱发电组织的核心驱动力:

    • 遵守开源守则,体现开源&贡献精神:以分享为目的,拒绝非法牟利。
    • 自我保护:使用适当的 License 保护自己的原创作品。
    • 尊重他人:不以各种理由、各种漏洞进行未经允许的抄袭、散播、洩露;以礼相待,尊重所有对社区做出贡献的开发者;通过他人的分享习得知识,要留下足迹,表示感谢。
    • 热爱编程、热爱学习:加入组织,热爱编程是首当其要的。我们欢迎热爱讨论、分享、提问的朋友,也同样欢迎默默成就的朋友。
    • 倾听:正确并恳切对待、处理问题与建议,及时修复开源项目的 Bug ,及时与反馈者沟通。不抬杠、不无视、不辱骂。
    • 平视:不诋毁、轻视、嘲讽其他开发者,主动提出建议、施以帮助,以和谐为本。只要他人肯努力,你也可能会被昔日小看的人所超越,所以请保持谦虚。
    • 乐观且活跃:你的努力决定了你的高度。不要放弃,多年后回头俯瞰,才会发现自己已经成就往日所仰望的水平。积极地将项目开源,帮助他人学习、改进,自己也会获得相应的提升、成就与成就感。
    1 引用 • 487 回帖
  • 新人

    让我们欢迎这对新人。哦,不好意思说错了,让我们欢迎这位新人!
    新手上路,请谨慎驾驶!

    52 引用 • 228 回帖
  • 数据库

    据说 99% 的性能瓶颈都在数据库。

    340 引用 • 708 回帖
  • Kotlin

    Kotlin 是一种在 Java 虚拟机上运行的静态类型编程语言,由 JetBrains 设计开发并开源。Kotlin 可以编译成 Java 字节码,也可以编译成 JavaScript,方便在没有 JVM 的设备上运行。在 Google I/O 2017 中,Google 宣布 Kotlin 成为 Android 官方开发语言。

    19 引用 • 33 回帖 • 63 关注
  • WebSocket

    WebSocket 是 HTML5 中定义的一种新协议,它实现了浏览器与服务器之间的全双工通信(full-duplex)。

    48 引用 • 206 回帖 • 333 关注
  • Java

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

    3187 引用 • 8213 回帖
  • SEO

    发布对别人有帮助的原创内容是最好的 SEO 方式。

    35 引用 • 200 回帖 • 22 关注
  • 安装

    你若安好,便是晴天。

    132 引用 • 1184 回帖
  • Hadoop

    Hadoop 是由 Apache 基金会所开发的一个分布式系统基础架构。用户可以在不了解分布式底层细节的情况下,开发分布式程序。充分利用集群的威力进行高速运算和存储。

    86 引用 • 122 回帖 • 625 关注
  • Thymeleaf

    Thymeleaf 是一款用于渲染 XML/XHTML/HTML5 内容的模板引擎。类似 Velocity、 FreeMarker 等,它也可以轻易的与 Spring 等 Web 框架进行集成作为 Web 应用的模板引擎。与其它模板引擎相比,Thymeleaf 最大的特点是能够直接在浏览器中打开并正确显示模板页面,而不需要启动整个 Web 应用。

    11 引用 • 19 回帖 • 354 关注
  • ZooKeeper

    ZooKeeper 是一个分布式的,开放源码的分布式应用程序协调服务,是 Google 的 Chubby 一个开源的实现,是 Hadoop 和 HBase 的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。

    59 引用 • 29 回帖 • 5 关注
  • V2Ray
    1 引用 • 15 回帖
  • Elasticsearch

    Elasticsearch 是一个基于 Lucene 的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于 RESTful 接口。Elasticsearch 是用 Java 开发的,并作为 Apache 许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。

    117 引用 • 99 回帖 • 211 关注
  • PHP

    PHP(Hypertext Preprocessor)是一种开源脚本语言。语法吸收了 C 语言、 Java 和 Perl 的特点,主要适用于 Web 开发领域,据说是世界上最好的编程语言。

    179 引用 • 407 回帖 • 488 关注
  • Sphinx

    Sphinx 是一个基于 SQL 的全文检索引擎,可以结合 MySQL、PostgreSQL 做全文搜索,它可以提供比数据库本身更专业的搜索功能,使得应用程序更容易实现专业化的全文检索。

    1 引用 • 211 关注
  • 资讯

    资讯是用户因为及时地获得它并利用它而能够在相对短的时间内给自己带来价值的信息,资讯有时效性和地域性。

    55 引用 • 85 回帖
  • 大数据

    大数据(big data)是指无法在一定时间范围内用常规软件工具进行捕捉、管理和处理的数据集合,是需要新处理模式才能具有更强的决策力、洞察发现力和流程优化能力的海量、高增长率和多样化的信息资产。

    93 引用 • 113 回帖
  • 开源

    Open Source, Open Mind, Open Sight, Open Future!

    408 引用 • 3574 回帖
  • Sublime

    Sublime Text 是一款可以用来写代码、写文章的文本编辑器。支持代码高亮、自动完成,还支持通过插件进行扩展。

    10 引用 • 5 回帖
  • jsoup

    jsoup 是一款 Java 的 HTML 解析器,可直接解析某个 URL 地址、HTML 文本内容。它提供了一套非常省力的 API,可通过 DOM,CSS 以及类似于 jQuery 的操作方法来取出和操作数据。

    6 引用 • 1 回帖 • 478 关注
  • ZeroNet

    ZeroNet 是一个基于比特币加密技术和 BT 网络技术的去中心化的、开放开源的网络和交流系统。

    1 引用 • 21 回帖 • 637 关注
  • CSS

    CSS(Cascading Style Sheet)“层叠样式表”是用于控制网页样式并允许将样式信息与网页内容分离的一种标记性语言。

    198 引用 • 550 回帖