读取类路径下的class文件
1.思路
加载class文件时,会从
启动类路径(/jre/lib),
扩展类路径(/jre/lib/ext),
用户类路径(用户当前路径),
中加载文件;
因此jvm启动时会将上述三种类型的路径读入内存中,当我们需要使用到某一具体的类文件时,就会从这些路径中加载(加载顺序为 启动类 -》扩展类 -》 用户类);
且加载文件的方式也有多种,如直接从文件夹中加载class文件,从jar中加载class文件,还有就是通配符*加载目录下全部文路劲(包括普通文件夹以及压缩包);
1.1.entry.go
可以从多个地方查找class文件,如jar,文件夹,因此面向接口编程,定义接口
package classpath
import (
"os"
"strings"
)
const pathListSeparator = string(os.PathListSeparator)
type Entry interface {
readClass(ClassName string) ([]byte, Entry, error)
String() string
}
func newEntry(path string) Entry
//若 -cp或-classpath中包含由分号分割的多个类文件,则将其分割并递归调用本函数
if strings.Contains(path, pathListSeparator) {
return newCompositeEntry(path)
}
//若-cp后的值包含*,则说明要将相应目录下的所有class文件加载
if strings.HasSuffix(path, "*") {
return newWildcardEntry(path)
}
//若-cp后的值包含.jar,则说明是jar文件,通过zip方式加载
if strings.HasSuffix(path, ".jar") || strings.HasSuffix(path, ".JAR") || strings.HasSuffix(path, ".zip") || strings.HasSuffix(path, ".ZIP") {
return newZipEntry(path)
}
return newDirEntry(path)
}
1.2.entry_dir
我们可以从目录下加载class文件
package classpath
import (
"io/ioutil"
"path/filepath"
)
//读取目录下的class文件
type DirEntry struct {
absDir string
}
func newDirEntry(path string) *DirEntry {
absDir, err := filepath.Abs(path)
if err != nil {
panic(err)
}
return &DirEntry{
absDir: absDir}
}
func (self *DirEntry) readClass(className string) ([]byte, Entry, error) {
fileName := filepath.Join(self.absDir, className)
data, err := ioutil.ReadFile(fileName)
return data, self, err
}
func (self *DirEntry) String() string {
return self.absDir
}
1.3.entry_zip.go
我们可以从jar包中加载class文件
package classpath
import (
"archive/zip"
"errors"
"io/ioutil"
"path/filepath"
)
//读取zip如.jar中读取class文件
type ZipEntry struct {
absPath string
}
func newZipEntry(path string) *ZipEntry {
absPath, err := filepath.Abs(path)
if err != nil {
panic(er