上一篇通过flag包实现了命令行参数的解析,其实就是将输入的参数保存到一个结构体中,上一篇说过的例如java -classpath hello.jar HelloWorld这种命令,那么HelloWorld这个类是怎么找出来的呢?是直接在hello.jar中去找吗?

  还记得java的类加载机制吗?有个叫做双亲委托机制,就比如我们自己定义一个String类为什么没用呢?虽然说编译时可以通过的,但是在运行的时候却会报错,如下所示,为什么提示String类中没有main方法呢,明明我就写了呀!其实是在类加载的时候,首先会把String类交给启动类加载器加载,也就是在jdk中jre/lib目录下去找;没有的话就使用扩展类加载器去加载,也就是在jdk中jre/lib/ext中去加载,最后才是我们用户的类路径下找,默认是当前路径,也可以通过-classpath命令指定用户类路径;

  而String类很明显在启动类路径下rt.jar包中,所以加载当的是官方的String类,当然没有main方法啦!

go实现java虚拟机02

 

  再回到最开始的问题,例如java -classpath hello.jar HelloWorld这种命令,HelloWorld这个类在哪里找,现在就很清楚了,现在jdk下jre/lib中找,找不到就到jre/lib/ext中找,还找不到就在-classpath指定的路径中找,下面就用go代码实现一下,文件目录如下,这次的目录是ch02,基于上一篇的ch01实现,classpath是一个目录,cmd.go和main.go是文件

go实现java虚拟机02

 

 一.命令行添加jre路径

  为了可以更好的指定jre路径,我们命令行中添加一个参数-Xjre,例如ch2 -Xjre “D:\java\jdk8” java.lang.String,如果命令行中没有指定-Xjre参数,那么就去你计算机环境变量中获取JAVA_HOME了,这就不多说了,所以我们要把cmd.go这里结构体做一个修改,以及对应的解析也添加一个,不多说;

go实现java虚拟机02

go实现java虚拟机02

   

  cmd.go

package main

import (
    "flag"
    "fmt"
    "os"
)

//这个结构体用保存命令行输入的参数,例如:.\ch02.exe -Xjre "D:\java\jdk8\jre" java.lang.Object
type Cmd struct {
    helpFlag    bool
    versionFlag bool
    cpOption    string
    XjreOption  string
    class       string
    args        []string
}

//命令行输入      .\ch02.exe -Xjre "D:\java\jdk8\jre" java.lang.Object
func parseCmd() *Cmd {
    cmd := &Cmd{}
    //这里的意思就是如果解析失败的话,就调用printUsage函数
    flag.Usage = printUsage
    //下面这些在控制台中表示的是-xxx,要匹配上,没有匹配上就报错
    //匹配上了的话,在-xxx后面的都是【表情】属于参数,其中第一个表示的是类名,后面的都是其他的参数
    flag.BoolVar(&cmd.helpFlag, "help", false, "print help message")
    flag.BoolVar(&cmd.versionFlag, "version", false, "print version and exit")
    flag.StringVar(&cmd.cpOption, "classpath", "", "classpath")
    //解析jre类路径
    flag.StringVar(&cmd.XjreOption, "Xjre", "", "path to jre")
    flag.Parse()
    args := flag.Args()
    //解析成功的话,那就继续获取后面的参数
    if len(args) > 0 {
        cmd.class = args[0]
        cmd.args = args[1:]
    }
    return cmd
}

//这里传进去的参数,解析错误的话就显示第一个参数的提示信息
func printUsage() {
    fmt.Printf("Usage:%s [-options] class [args]\n", os.Args[0])
}
View Code

相关文章: