【JVM】手写Java虚拟机-01 命令行工具

2023-10-29

介绍

手写一个简单的Java虚拟机,参考了bugstack虫洞栈声哥,《自己动手写Java虚拟机》,和JVM-Demo

本系列文章尽可能按照保姆级呈现。

如果有任何问题和建议,请联系我。

环境

操作系统:Windows 10

IDE:IntelliJ IDEA 2019.1 x64

JDK:Java 11.0.8

项目管理工具:apache-maven-3.5.4 [下载]

配置环境

Java的安装网上很多教程,就不赘述了。

注意安装Maven时,解压好之后要修改系统路径。然后试试调用cmd的mvn -v命令,如果调用不出来,重启即可。

在这里插入图片描述

注意Maven的版本要和IDEA匹配,Maven版本不要比IDEA版本高,否则报错就不好了。

可能遇到的问题

开始项目了,打开IDEA,创建一个Maven项目。

在这里插入图片描述

创建pom.xml文件,直接拉到下面把我的pom.xml复制过来,然后试试能不能import。
在这里插入图片描述

如果不能,先在IDEA中把Maven home改了试试,就改为你的Maven安装(解压)地址(maven-repo是自己创建的):
在这里插入图片描述

如果报错,log中出现 IDEA 2019 Unable to get current time from Google’s servers,那么可以试试禁用android support 插件:

在这里插入图片描述

如果报错 异常:[ERROR] 不再支持源选项 1.5。请使用 1.6 或更高版本 ,可能是因为java版本声明不对,在pom.xml中已经添加了java版本属性就可以解决:

    <!-- 添加属性:使用的java版本为java11 -->
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.encoding>UTF-8</maven.compiler.encoding>
        <java.version>1.8</java.version>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
    </properties>

开始:命令行工具

simpleJVM-01
├── pom.xml
└── src
    └── main
    │    └── java
    │        └── cn.zwy.simplejvm
    │		      ├── Cmd.java
    │ 		      └── Main.java
    └── test
		 └── java
			 └── cn.zwy.test
				 └── HelloWorld.java

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>cn.zwy</groupId>
    <artifactId>simpleJVM-01</artifactId>
    <version>1.0-SNAPSHOT</version>

    <!-- 添加属性:使用的java版本为java11 -->
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.encoding>UTF-8</maven.compiler.encoding>
        <java.version>1.8</java.version>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
    </properties>

    <dependencies>
        <!-- 解析命令行参数 -->
        <dependency>
            <groupId>com.beust</groupId>
            <artifactId>jcommander</artifactId>
            <version>1.78</version>
        </dependency>
    </dependencies>

</project>

Cmd.java

package cn.zwy.simplejvm;

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

import java.util.List;

/**
 * @author weiyu_zeng
 *
 * Parameter函数参数:
 * names 设置命令行参数,如-old
 * required 设置此参数是否必须
 * description 设置参数的描述
 * order 设置帮助文档的顺序
 * help 设置此参数是否为展示帮助文档或者辅助功能
 */
public class Cmd {

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

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

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

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

    boolean ok;

    // 返回mainClassAndArgs的Class(List<String>的第一个参数)
    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;
    }

    // 解析函数:传入String[] argv,返回Cmd类
    static Cmd parse(String[] argv) {
        Cmd args = new Cmd();
        JCommander cmd = JCommander.newBuilder().addObject(args).build();
        cmd.parse(argv);  // 调用JCommander中的parse函数解析
        args.ok = true;  // 将ok标志位置为true
        return args;
    }
}

Main.java

package cn.zwy.simplejvm;

public class Main {

    public static void main(String[] args) {
        Cmd cmd = Cmd.parse(args);
        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);
    }

    // %s链接后面的变量
    // 分别打印classpath, getMainClass()返回值,和getAppArgs()返回值
    private static void startJVM(Cmd cmd) {
        System.out.printf("classpath:%s class:%s args:%s\n", 
                cmd.classpath,
                cmd.getMainClass(), 
                cmd.getAppArgs());
    }
}

HelloWorld.java

package cn.zwy.test;

public class HelloWorld {

    public static void main(String[] args) {
        System.out.println("hello world");
    }
}

执行

可以直接执行Main.java。

在这里插入图片描述
目前还啥也没有:

classpath:null class:null args:null

点Edit Configurations

在这里插入图片描述
添加program argument:-version,激活我们定义的boolean versionFlag:
在这里插入图片描述
可以得到输出:

java version "1.8.0"

添加program argument:-help,激活我们定义的boolean helpFlag:

在这里插入图片描述

可以得到输出:

Usage: <main class> [-options] class [args...]
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【JVM】手写Java虚拟机-01 命令行工具 的相关文章

  • Spring Batch 多线程 - 如何使每个线程读取唯一的记录?

    这个问题在很多论坛上都被问过很多次了 但我没有看到适合我的答案 我正在尝试在我的 Spring Batch 实现中实现多线程步骤 有一个包含 100k 条记录的临时表 想要在 10 个线程中处理它 每个线程的提交间隔为 300 因此在任何时
  • 如何在 Play java 中创建数据库线程池并使用该池进行数据库查询

    我目前正在使用 play java 并使用默认线程池进行数据库查询 但了解使用数据库线程池进行数据库查询可以使我的系统更加高效 目前我的代码是 import play libs Akka import scala concurrent Ex
  • Java - 将节点添加到列表的末尾?

    这是我所拥有的 public class Node Object data Node next Node Object data Node next this data data this next next public Object g
  • 制作一个交互式Windows服务

    我希望我的 Java 应用程序成为交互式 Windows 服务 用户登录时具有 GUI 的 Windows 服务 我搜索了这个 我发现这样做的方法是有两个程序 第一个是服务 第二个是 GUI 程序并使它们进行通信 服务将从 GUI 程序获取
  • 无法展开 RemoteViews - 错误通知

    最近 我收到越来越多的用户收到 RemoteServiceException 错误的报告 我每次给出的堆栈跟踪如下 android app RemoteServiceException Bad notification posted fro
  • 多个 Maven 配置文件激活多个 Spring 配置文件

    我想在 Maven 中构建一个环境 在其中我想根据哪些 Maven 配置文件处于活动状态来累积激活多个 spring 配置文件 目前我的 pom xml 的相关部分如下所示
  • Spark 1.3.1 上的 Apache Phoenix(4.3.1 和 4.4.0-HBase-0.98)ClassNotFoundException

    我正在尝试通过 Spark 连接到 Phoenix 并且在通过 JDBC 驱动程序打开连接时不断收到以下异常 为简洁起见 下面是完整的堆栈跟踪 Caused by java lang ClassNotFoundException org a
  • Spring Data JPA 应用排序、分页以及 where 子句

    我目前正在使用 Spring JPA 并利用此处所述的排序和分页 如何通过Spring data JPA通过排序和可分页查询数据 https stackoverflow com questions 10527124 how to query
  • 无法解析插件 Java Spring

    我正在使用 IntelliJ IDEA 并且我尝试通过 maven 安装依赖项 但它给了我这些错误 Cannot resolve plugin org apache maven plugins maven clean plugin 3 0
  • 如何为俚语和表情符号构建正则表达式 (regex)

    我需要构建一个正则表达式来匹配俚语 即 lol lmao imo 等 和表情符号 即 P 等 我按照以下示例进行操作http www coderanch com t 497238 java java Regular Expression D
  • 为什么HashMap不能保证map的顺序随着时间的推移保持不变

    我在这里阅读有关 Hashmap 和 Hashtable 之间的区别 http javarevisited blogspot sg 2010 10 difference Between hashmap and html http javar
  • AWS 无法从 START_OBJECT 中反序列化 java.lang.String 实例

    我创建了一个 Lambda 函数 我想在 API 网关的帮助下通过 URL 访问它 我已经把一切都设置好了 我还创建了一个application jsonAPI Gateway 中的正文映射模板如下所示 input input params
  • Eclipse Java 远程调试器通过 VPN 速度极慢

    我有时被迫离开办公室工作 这意味着我需要通过 VPN 进入我的实验室 我注意到在这种情况下使用 Eclipse 进行远程调试速度非常慢 速度慢到调试器需要 5 7 分钟才能连接到远程 jvm 连接后 每次单步执行断点 行可能需要 20 30
  • Java执行器服务线程池[关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 如果我使用 Executor 框架在
  • Android 中麦克风的后台访问

    是否可以通过 Android 手机上的后台应用程序 服务 持续监控麦克风 我想做的一些想法 不断聆听背景中的声音信号 收到 有趣的 音频信号后 执行一些网络操作 如果前台应用程序需要的话 后台应用程序必须能够智能地放弃对麦克风的访问 除非可
  • 如何在桌面浏览器上使用 webdriver 移动网络

    我正在使用 selenium webdriver 进行 AUT 被测应用程序 的功能测试自动化 AUT 是响应式网络 我几乎完成了桌面浏览器的不同测试用例 现在 相同的测试用例也适用于移动浏览器 因为可以从移动浏览器访问 AUT 由于它是响
  • simpleframework,将空元素反序列化为空字符串而不是 null

    我使用简单框架 http simple sourceforge net http simple sourceforge net 在一个项目中满足我的序列化 反序列化需求 但在处理空 空字符串值时它不能按预期工作 好吧 至少不是我所期望的 如
  • 使用 JMF 创建 RTP 流时出现问题

    我正处于一个项目的早期阶段 需要使用 RTP 广播DataStream创建自MediaLocation 我正在遵循一些示例代码 该代码目前在rptManager initalize localAddress 出现错误 无法打开本地数据端口
  • 当我从 Netbeans 创建 Derby 数据库时,它存储在哪里?

    当我从 netbeans 创建 Derby 数据库时 它存储在哪里 如何将它与项目的其余部分合并到一个文件夹中 右键单击Databases gt JavaDB in the Service查看并选择Properties This will
  • JGit 检查分支是否已签出

    我正在使用 JGit 开发一个项目 我设法删除了一个分支 但我还想检查该分支是否已签出 我发现了一个变量CheckoutCommand但它是私有的 private boolean isCheckoutIndex return startCo

随机推荐

  • unity 设置一键重启

    以前的游戏里用过 后来查reference怎么也找不到当时用的代码了 重新看了一下工程发现是用playmaker实现的
  • [288]关于MySQL的1064错误

    MySQL的1064错误是SQL语句写的有问题时出现的 即SQL的语法错误 笔者常常使用MySQL python这个库来对MySQL进行操作 代码中报这个错误的一般是cursor execute sql param 这一行 这种参数式执行S
  • Vue的Ui框架之Mint-UI的使用方法

    基于Vue的Ui框架 饿了么公司基于vue开发的vue的Ui组件库 Element Ui 基于vue pc端的UI框架 MintUi 基于vue 移动端的ui框架 mintUI的使用 1 找官网 2 安装 npm install mint
  • stm32 freeRTOS lwip TCP快速发送,内存泄露问题

    现象1 发送缓慢 tcp write之后要等200多ms才能过发送出去 而且粘包严重 解决办法 tcp write之后 立马调用tcp output tcp就会立马发送 tcp write tcp output 现象2 持续快速发送和接受T
  • linux top VIRT RES SHR SWAP DATA内存参数详解

    总结 VIRT 虚拟内存中含有共享库 共享内存 栈 堆 所有已申请的总内存空间 RES 是进程正在使用的内存空间 栈 堆 申请内存后该内存段已被重新赋值 SHR 是共享内存正在使用的空间 SWAP 交换的是已经申请 但没有使用的空间 包括
  • cookie的读写设计和浏览器控制台Application设计不一致?

    问题描述 在做需求联调的时候发现 用https的链接登录状态验证正常 但是在http协议下 会出现set cookie失败的情况 导致登录状态验证失败 查看控制台 报错如下 提示 会覆盖具有 Secure 属性的cookie 于是在控制台下
  • C语言:以分号结尾的诗

    目录 前言 1 从Hello world开始 2 数据的类型与运算 2 1 整形在内存中的存储 2 1 1 从二进制说起 2 1 2 数据类型 2 1 2 1 数据类型家族 2 1 2 2 比特 字节 2 1 3 原码 反码 补码 2 1
  • cookie保存,json、字符串相互转换

    cookie读写操作 addcookie函数中 对text进行了eacape编码 方便在各种浏览器 下都可以读取 所以取值的时候需要unescape 解码 function getCookie name var strCookie docu
  • Windows下性能最好的I/O模型——完成端口

    Windows下性能最好的I O模型 完成端口 I O模型 完成端口 设计目的 常见的网络通信分为两种 同步和异步 在同步通信中 每一次接受数据都会导致主线程的挂起 从而阻塞住了其他操作 为了解决这一问题 我们通常会采取同步通信 多线程的策
  • 一个关于Python字符串格式化输出的练习

    请实现一个程序 实现如下需求点 1 程序开始的时候提示用户输入学生年龄信息 格式如下 Jack Green 21 Mike Mos 9 我们假设 用户输入 上面的信息 必定会遵守下面的规则 学生信息之间用分号隔开 分号前后可能有不定数量的空
  • 延时函数中用全局变量还是用局部变量

    从不上系统角度 如果中断函数中没有调用延时函数 就都可以 但是如果中断函数中有用到延时函数 就用 局部变量 因此 全部使用局部变量最好
  • 一次磁盘占用率 100% 的排查记录

    一 排查磁盘占用率100 1 1 查看磁盘使用的大致情况 第一个命令就是 df h 来查看磁盘的占用情况 df 是 disk free 的缩写 用于显示目前在 Linux 系统上的文件系统磁盘的使用情况统计 如下图所示 可以看到磁盘占用率
  • Exoplayer+Exomedia之玩转视频播放事件监听

    说明 视频播放事件包括两个部分 1 播放器本身的事件 开始 暂停 结束播放等 2 用户动作触发的事件 拖拽进度条 点击屏幕等 播放事件监听的途径主要是通过视频播放框架 或开发者自定义 的控制器来实现的 控制器是指操作播放器的组件 按钮 进度
  • 信号完整性分析基础知识之传输线和反射(二):阻性负载的反射,源端阻抗,弹跳图

    传输线的端接需要考虑三种重要的特殊情况 每种情况中 传输线的特性阻抗均为50Ohm 信号将从源端在这条传输线上传播 并以特定的阻抗端接到达远端 TIP 在时域中 信号对瞬时阻抗十分敏感 第二区域并不一定是一条传输线 它也可能是一个分立设备
  • Ubuntu14.04上安装TensorRT 2.1操作步骤

    在Ubuntu14 04 上安装TensorRT2 1有两种方法 1 通过 deb直接安装 2 通过Tar文件安装 这里通过Tar文件安装 安装步骤 1 安装CUDA 8 0 可参考 http blog csdn net fengbingc
  • 离散系统Matlab信号处理

    一 离散时间信号 代码 n 2 7 x 0 2 3 5 6 1 5 7 9 2 subplot 2 1 1 stem n x xlabel n ylabel x n title stem函数绘制离散信号 subplot 2 1 2 plot
  • 使用scrapy cluster构建企业级爬虫系统——(2)实现网站深度抓取

    上回博客中 我们对scrapy cluster进行了介绍 今天我们来搭建scrapy cluster的开发环境 这里我使用的开发机环境是Ubuntu 18 04 大家日常如果使用windows开发时候 最好把zookeeper kafka
  • .Xauthority文件 有问题,导致无法登录

    在用户 home目录下的 Xauthority文件 解决办法 1 修改 2 rm 删除 重启
  • 管理习惯---思维转变

    福州 雨 湿热 简单描述 想起了香港的蜗居 当然 中庸的福州美于香港不止一点 参加了 管理他人者 说道执行 涉及内容 确定方向与明确目标 授权与跟进 发张直属下级 评估和改善绩效 选择团队成员和建设团队 时间分配 上级谈话 课程来说 偏向中
  • 【JVM】手写Java虚拟机-01 命令行工具

    目录 介绍 环境 配置环境 可能遇到的问题 开始 命令行工具 执行 介绍 手写一个简单的Java虚拟机 参考了bugstack虫洞栈 声哥 自己动手写Java虚拟机 和JVM Demo 本系列文章尽可能按照保姆级呈现 如果有任何问题和建议