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

介绍

手写一个简单的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...]
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

锥栗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值