- 自己动手写Java虚拟机
- 张秀宏
- 575字
- 2023-01-30 16:12:48
2.3.6 Classpath
Entry接口和4个实现介绍完了,接下来实现Classpath结构体。还是在ch02\classpath目录下创建classpath.go文件,把下面的代码输入进去。
package classpath import "os" import "path/filepath" type Classpath struct { bootClasspath Entry extClasspath Entry userClasspath Entry } func Parse(jreOption, cpOption string) *Classpath {...} func (self *Classpath) ReadClass(className string) ([]byte, Entry, error) {...} func (self *Classpath) String() string {...}
Classpath结构体有三个字段,分别存放三种类路径。Parse()函数使用-Xjre选项解析启动类路径和扩展类路径,使用-classpath/-cp选项解析用户类路径,代码如下:
func Parse(jreOption, cpOption string) *Classpath { cp := &Classpath{} cp.parseBootAndExtClasspath(jreOption) cp.parseUserClasspath(cpOption) return cp }
parseBootAndExtClasspath()方法的代码如下:
func (self *Classpath) parseBootAndExtClasspath(jreOption string) { jreDir := getJreDir(jreOption) // jre/lib/* jreLibPath := filepath.Join(jreDir, "lib", "*") self.bootClasspath = newWildcardEntry(jreLibPath) // jre/lib/ext/* jreExtPath := filepath.Join(jreDir, "lib", "ext", "*") self.extClasspath = newWildcardEntry(jreExtPath) }
优先使用用户输入的-Xjre选项作为jre目录。如果没有输入该选项,则在当前目录下寻找jre目录。如果找不到,尝试使用JAVA_HOME环境变量。getJreDir()函数的代码如下:
func getJreDir(jreOption string) string { if jreOption ! = "" && exists(jreOption) { return jreOption } if exists("./jre") { return "./jre" } if jh := os.Getenv("JAVA_HOME"); jh ! = "" { return filepath.Join(jh, "jre") } panic("Can not find jre folder! ") }
exists()函数用于判断目录是否存在,代码如下:
func exists(path string) bool { if _, err := os.Stat(path); err ! = nil { if os.IsNotExist(err) { return false } } return true }
parseUserClasspath()方法的代码相对简单一些,如下:
func (self *Classpath) parseUserClasspath(cpOption string) { if cpOption == "" { cpOption = "." } self.userClasspath = newEntry(cpOption) }
如果用户没有提供-classpath/-cp选项,则使用当前目录作为用户类路径。ReadClass()方法依次从启动类路径、扩展类路径和用户类路径中搜索class文件,代码如下:
func (self *Classpath) ReadClass(className string) ([]byte, Entry, error) { className = className + ".class" if data, entry, err := self.bootClasspath.readClass(className); err == nil { return data, entry, err } if data, entry, err := self.extClasspath.readClass(className); err == nil { return data, entry, err } return self.userClasspath.readClass(className) }
注意,传递给ReadClass()方法的类名不包含“.class”后缀。最后,String()方法返回用户类路径的字符串表示,代码如下:
func (self *Classpath) String() string { return self.userClasspath.String() }
至此,整个类路径都实现了,下面我们来测试一下。