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

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

参考资料:《深入理解 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 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3202 引用 • 8217 回帖 • 1 关注

相关帖子

欢迎来到这里!

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

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

推荐标签 标签

  • Love2D

    Love2D 是一个开源的, 跨平台的 2D 游戏引擎。使用纯 Lua 脚本来进行游戏开发。目前支持的平台有 Windows, Mac OS X, Linux, Android 和 iOS。

    14 引用 • 53 回帖 • 563 关注
  • HTML

    HTML5 是 HTML 下一个的主要修订版本,现在仍处于发展阶段。广义论及 HTML5 时,实际指的是包括 HTML、CSS 和 JavaScript 在内的一套技术组合。

    108 引用 • 295 回帖 • 2 关注
  • RESTful

    一种软件架构设计风格而不是标准,提供了一组设计原则和约束条件,主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。

    30 引用 • 114 回帖 • 8 关注
  • 又拍云

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

    20 引用 • 37 回帖 • 573 关注
  • Bootstrap

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

    18 引用 • 33 回帖 • 649 关注
  • 智能合约

    智能合约(Smart contract)是一种旨在以信息化方式传播、验证或执行合同的计算机协议。智能合约允许在没有第三方的情况下进行可信交易,这些交易可追踪且不可逆转。智能合约概念于 1994 年由 Nick Szabo 首次提出。

    1 引用 • 11 回帖
  • Vue.js

    Vue.js(读音 /vju ː/,类似于 view)是一个构建数据驱动的 Web 界面库。Vue.js 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。

    268 引用 • 666 回帖 • 2 关注
  • 阿里云

    阿里云是阿里巴巴集团旗下公司,是全球领先的云计算及人工智能科技公司。提供云服务器、云数据库、云安全等云计算服务,以及大数据、人工智能服务、精准定制基于场景的行业解决方案。

    85 引用 • 324 回帖 • 1 关注
  • JVM

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

    180 引用 • 120 回帖 • 2 关注
  • 印象笔记
    3 引用 • 16 回帖 • 2 关注
  • OpenCV
    15 引用 • 36 回帖
  • Electron

    Electron 基于 Chromium 和 Node.js,让你可以使用 HTML、CSS 和 JavaScript 构建应用。它是一个由 GitHub 及众多贡献者组成的活跃社区共同维护的开源项目,兼容 Mac、Windows 和 Linux,它构建的应用可在这三个操作系统上面运行。

    15 引用 • 136 回帖 • 1 关注
  • FlowUs

    FlowUs.息流 个人及团队的新一代生产力工具。

    让复杂的信息管理更轻松、自由、充满创意。

    1 引用 • 1 关注
  • IPFS

    IPFS(InterPlanetary File System,星际文件系统)是永久的、去中心化保存和共享文件的方法,这是一种内容可寻址、版本化、点对点超媒体的分布式协议。请浏览 IPFS 入门笔记了解更多细节。

    20 引用 • 245 回帖 • 234 关注
  • 知乎

    知乎是网络问答社区,连接各行各业的用户。用户分享着彼此的知识、经验和见解,为中文互联网源源不断地提供多种多样的信息。

    10 引用 • 66 回帖 • 2 关注
  • Git

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

    211 引用 • 358 回帖 • 2 关注
  • GitBook

    GitBook 使您的团队可以轻松编写和维护高质量的文档。 分享知识,提高团队的工作效率,让用户满意。

    3 引用 • 8 回帖
  • 代码片段

    代码片段分为 CSS 与 JS 两种代码,添加在 [设置 - 外观 - 代码片段] 中,这些代码会在思源笔记加载时自动执行,用于改善笔记的样式或功能。

    用户在该标签下分享代码片段时需在帖子标题前添加 [css] [js] 用于区分代码片段类型。

    204 引用 • 1476 回帖
  • Ngui

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

    7 引用 • 9 回帖 • 408 关注
  • Angular

    AngularAngularJS 的新版本。

    26 引用 • 66 回帖 • 563 关注
  • Dubbo

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

    60 引用 • 82 回帖 • 617 关注
  • 叶归
    13 引用 • 59 回帖 • 22 关注
  • Vim

    Vim 是类 UNIX 系统文本编辑器 Vi 的加强版本,加入了更多特性来帮助编辑源代码。Vim 的部分增强功能包括文件比较(vimdiff)、语法高亮、全面的帮助系统、本地脚本(Vimscript)和便于选择的可视化模式。

    29 引用 • 66 回帖
  • 小说

    小说是以刻画人物形象为中心,通过完整的故事情节和环境描写来反映社会生活的文学体裁。

    32 引用 • 108 回帖
  • Webswing

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

    1 引用 • 15 回帖 • 642 关注
  • 支付宝

    支付宝是全球领先的独立第三方支付平台,致力于为广大用户提供安全快速的电子支付/网上支付/安全支付/手机支付体验,及转账收款/水电煤缴费/信用卡还款/AA 收款等生活服务应用。

    29 引用 • 347 回帖
  • CloudFoundry

    Cloud Foundry 是 VMware 推出的业界第一个开源 PaaS 云平台,它支持多种框架、语言、运行时环境、云平台及应用服务,使开发人员能够在几秒钟内进行应用程序的部署和扩展,无需担心任何基础架构的问题。

    4 引用 • 16 回帖 • 197 关注