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

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

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

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

    3168 引用 • 8207 回帖

相关帖子

欢迎来到这里!

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

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

推荐标签 标签

  • 学习

    “梦想从学习开始,事业从实践起步” —— 习近平

    161 引用 • 473 回帖
  • Hprose

    Hprose 是一款先进的轻量级、跨语言、跨平台、无侵入式、高性能动态远程对象调用引擎库。它不仅简单易用,而且功能强大。你无需专门学习,只需看上几眼,就能用它轻松构建分布式应用系统。

    9 引用 • 17 回帖 • 598 关注
  • RIP

    愿逝者安息!

    8 引用 • 92 回帖 • 291 关注
  • OAuth

    OAuth 协议为用户资源的授权提供了一个安全的、开放而又简易的标准。与以往的授权方式不同之处是 oAuth 的授权不会使第三方触及到用户的帐号信息(如用户名与密码),即第三方无需使用用户的用户名与密码就可以申请获得该用户资源的授权,因此 oAuth 是安全的。oAuth 是 Open Authorization 的简写。

    36 引用 • 103 回帖 • 10 关注
  • 域名

    域名(Domain Name),简称域名、网域,是由一串用点分隔的名字组成的 Internet 上某一台计算机或计算机组的名称,用于在数据传输时标识计算机的电子方位(有时也指地理位置)。

    43 引用 • 208 回帖 • 2 关注
  • 七牛云

    七牛云是国内领先的企业级公有云服务商,致力于打造以数据为核心的场景化 PaaS 服务。围绕富媒体场景,七牛先后推出了对象存储,融合 CDN 加速,数据通用处理,内容反垃圾服务,以及直播云服务等。

    25 引用 • 215 回帖 • 165 关注
  • Openfire

    Openfire 是开源的、基于可拓展通讯和表示协议 (XMPP)、采用 Java 编程语言开发的实时协作服务器。Openfire 的效率很高,单台服务器可支持上万并发用户。

    6 引用 • 7 回帖 • 89 关注
  • Ngui

    Ngui 是一个 GUI 的排版显示引擎和跨平台的 GUI 应用程序开发框架,基于
    Node.js / OpenGL。目标是在此基础上开发 GUI 应用程序可拥有开发 WEB 应用般简单与速度同时兼顾 Native 应用程序的性能与体验。

    7 引用 • 9 回帖 • 345 关注
  • RabbitMQ

    RabbitMQ 是一个开源的 AMQP 实现,服务器端用 Erlang 语言编写,支持多种语言客户端,如:Python、Ruby、.NET、Java、C、PHP、ActionScript 等。用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。

    49 引用 • 60 回帖 • 396 关注
  • PWA

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

    14 引用 • 69 回帖 • 133 关注
  • 开源中国

    开源中国是目前中国最大的开源技术社区。传播开源的理念,推广开源项目,为 IT 开发者提供了一个发现、使用、并交流开源技术的平台。目前开源中国社区已收录超过两万款开源软件。

    7 引用 • 86 回帖 • 1 关注
  • abitmean

    有点意思就行了

    22 关注
  • PHP

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

    164 引用 • 407 回帖 • 527 关注
  • 小薇

    小薇是一个用 Java 写的 QQ 聊天机器人 Web 服务,可以用于社群互动。

    由于 Smart QQ 从 2019 年 1 月 1 日起停止服务,所以该项目也已经停止维护了!

    34 引用 • 467 回帖 • 693 关注
  • Firefox

    Mozilla Firefox 中文俗称“火狐”(正式缩写为 Fx 或 fx,非正式缩写为 FF),是一个开源的网页浏览器,使用 Gecko 排版引擎,支持多种操作系统,如 Windows、OSX 及 Linux 等。

    7 引用 • 30 回帖 • 451 关注
  • GAE

    Google App Engine(GAE)是 Google 管理的数据中心中用于 WEB 应用程序的开发和托管的平台。2008 年 4 月 发布第一个测试版本。目前支持 Python、Java 和 Go 开发部署。全球已有数十万的开发者在其上开发了众多的应用。

    14 引用 • 42 回帖 • 687 关注
  • 旅游

    希望你我能在旅途中找到人生的下一站。

    85 引用 • 895 回帖
  • 安全

    安全永远都不是一个小问题。

    189 引用 • 813 回帖
  • Eclipse

    Eclipse 是一个开放源代码的、基于 Java 的可扩展开发平台。就其本身而言,它只是一个框架和一组服务,用于通过插件组件构建开发环境。

    75 引用 • 258 回帖 • 627 关注
  • 大数据

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

    89 引用 • 113 回帖
  • TensorFlow

    TensorFlow 是一个采用数据流图(data flow graphs),用于数值计算的开源软件库。节点(Nodes)在图中表示数学操作,图中的线(edges)则表示在节点间相互联系的多维数据数组,即张量(tensor)。

    20 引用 • 19 回帖
  • Node.js

    Node.js 是一个基于 Chrome JavaScript 运行时建立的平台, 用于方便地搭建响应速度快、易于扩展的网络应用。Node.js 使用事件驱动, 非阻塞 I/O 模型而得以轻量和高效。

    138 引用 • 268 回帖 • 194 关注
  • Gitea

    Gitea 是一个开源社区驱动的轻量级代码托管解决方案,后端采用 Go 编写,采用 MIT 许可证。

    4 引用 • 16 回帖 • 1 关注
  • Swift

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

    34 引用 • 37 回帖 • 497 关注
  • Solo

    Solo 是一款小而美的开源博客系统,专为程序员设计。Solo 有着非常活跃的社区,可将文章作为帖子推送到社区,来自社区的回帖将作为博客评论进行联动(具体细节请浏览 B3log 构思 - 分布式社区网络)。

    这是一种全新的网络社区体验,让热爱记录和分享的你不再感到孤单!

    1425 引用 • 10043 回帖 • 469 关注
  • SendCloud

    SendCloud 由搜狐武汉研发中心孵化的项目,是致力于为开发者提供高质量的触发邮件服务的云端邮件发送平台,为开发者提供便利的 API 接口来调用服务,让邮件准确迅速到达用户收件箱并获得强大的追踪数据。

    2 引用 • 8 回帖 • 439 关注
  • danl
    62 关注