项目地址:https://github.com/gongxianshengjiadexiaohuihui
首先是定义一个抽象类,把四种路径的格式抽象出来
Entry.java
package classpath;
import java.io.IOException;
/**
* @ClassName Entry
* @Description TODO
* @Author Mr.G
* @Date 2018/10/12 15:31
* @Version 1.0
*/
public abstract class Entry {
/**
* 路径分隔符,windows用; liunx/unix 用 :
*/
public static final String PATHLISTSEPARATOR = System.getProperty("os.name").contains("Windows") ? ";" : ":" ;
/**
* 负责寻找和加载class文件
* @param className
* @return
* @throws IOException
*/
public abstract byte[] readClass(String className) throws IOException;
/**
*
* @return 返回路径的字符串形式
*/
public abstract String printAbsPath();
/**
* 工厂方法,根据传入路径的格式返回不同格式路径的实体类
* @param path
* @return
*/
public static Entry newEntry(String path){
if (path.contains(PATHLISTSEPARATOR)){
return new CompositeEntry(path);
}
if(path.contains("*")){
return new WildcardEntry(path);
}
if(path.contains(".jar") || path.contains(".JAR") || path.contains(".zip") || path.contains(".ZIP")){
return new ZipJarEntry(path);
}
return new DirEntry(path);
}
}
然后写具体实现
DirEntry.java
package classpath;
import java.io.*;
/**
* @ClassName DirEntry
* @Description TODO
* @Author Mr.G
* @Date 2018/10/12 15:50
* @Version 1.0
*/
public class DirEntry extends Entry {
private String absDir;
public DirEntry(String path){
File dir = new File(path);
if(dir.exists()){
absDir=dir.getAbsolutePath();
}
}
/**
* 负责寻找和加载class文件
*
* @param className
* @return
* @throws IOException
*/
@Override
public byte[] readClass(String className) throws IOException {
File file = new File(absDir,className);
byte[] temp = new byte[100];
BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));
ByteArrayOutputStream out = new ByteArrayOutputStream((int)file.length());
int length=0;
while((length=in.read(temp))!=-1){
out.write(temp,0,length);
}
if(in != null ){
in.close();
}
if(out != null){
out.close();
}
return out.toByteArray();
}
/**
* @return 返回路径的字符串形式
*/
@Override
public String printAbsPath() {
return absDir;
}
}
ZipJarEntry.java
package classpath;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
/**
* @ClassName ZipJarEntry
* @Description TODO
* @Author Mr.G
* @Date 2018/10/12 16:22
* @Version 1.0
*/
public class ZipJarEntry extends Entry {
private String absPath;
private String zipName;
public ZipJarEntry(String path){
File file = new File(path);
if(file.exists()){
absPath = file.getAbsolutePath();
zipName = file.getName();
//去掉结尾的.jar或.zip
zipName = zipName.substring(0,zipName.length() - 4 );
}
}
/**
* 负责寻找和加载class文件
*
* @param className
* @return
* @throws IOException
*/
@Override
public byte[] readClass(String className) throws IOException {
File file = new File (absPath);
ZipFile zf =new ZipFile(file);
ZipEntry zipEntry=null;
/**
* 根据后缀不同获取实体类
*/
if(absPath.contains(".zip")||absPath.contains(".ZIP")){
zipEntry = zf.getEntry(zipName+"/"+className);
}else{
zipEntry = zf.getEntry(className);
}
if(zipEntry == null){
return null;
}
BufferedInputStream in = new BufferedInputStream(zf.getInputStream(zipEntry));
ByteArrayOutputStream out = new ByteArrayOutputStream((int)zipEntry.getSize());
int length = 0;
byte[] temp = new byte[1024];
while((length = in.read(temp)) != -1){
out.write(temp,0,length);
}
if(in != null){
in.close();
}
if(out != null){
out.close();
}
return out.toByteArray();
}
/**
* @return 返回路径的字符串形式
*/
@Override
public String printAbsPath() {
return absPath;
}
}
CompositeEntry.java
package classpath;
import java.io.IOException;
import java.util.ArrayList;
/**
* @ClassName CompositeEntry
* @Description TODO
* @Author Mr.G
* @Date 2018/10/12 17:04
* @Version 1.0
*/
public class CompositeEntry extends Entry {
private String pathList;
public ArrayList<Entry> compositeEntry;
public CompositeEntry(){}
public CompositeEntry(String path){
this.pathList = path;
String[] paths = pathList.split(Entry.PATHLISTSEPARATOR);
compositeEntry = new ArrayList<Entry>(paths.length);
for(int i = 0; i < paths.length; i++){
compositeEntry.add(newEntry(paths[i]));
}
}
/**
* 负责寻找和加载class文件
*
* @param className
* @return
* @throws IOException
*/
@Override
public byte[] readClass(String className) throws IOException {
byte[] data;
for(Entry entry:compositeEntry){
data =entry.readClass(className);
if(data != null){
return data;
}
}
return null;
}
/**
* @return 返回路径的字符串形式
*/
@Override
public String printAbsPath() {
return pathList;
}
}
WildcardEntry.java
package classpath;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
/**
* @ClassName WildcardEntry
* @Description TODO
* @Author Mr.G
* @Date 2018/10/12 17:17
* @Version 1.0
*/
public class WildcardEntry extends Entry {
private CompositeEntry compositeEntry;
private String path;
public WildcardEntry(String path){
this.path=path;
/**
* 去掉*
*/
String baseDir = path.substring(0,path.length()-1);
File dir = new File(baseDir);
File[] files = dir.listFiles();
compositeEntry = new CompositeEntry();
compositeEntry.compositeEntry=new ArrayList<Entry>();
for(File file : files){
if((file.isFile()) && (file.getName().endsWith(".jar") || file.getName().endsWith(".JAR"))){
compositeEntry.compositeEntry.add(new ZipJarEntry(baseDir+"/"+file.getName()));
}
}
}
/**
* 负责寻找和加载class文件
*
* @param className
* @return
* @throws IOException
*/
@Override
public byte[] readClass(String className) throws IOException {
return compositeEntry.readClass(className);
}
/**
* @return 返回路径的字符串形式
*/
@Override
public String printAbsPath() {
return path ;
}
}
四种实现写好了,然后写classpath.java去封装上面四种格式的路径,成为对外的唯一接口
package classpath;
import java.io.File;
import java.io.IOException;
/**
* @ClassName ClassPath
* @Description TODO
* @Author Mr.G
* @Date 2018/10/13 9:07
* @Version 1.0
*/
public class ClassPath {
/**
* 启动类路径
*/
private Entry bootstrapClasspath;
/**
* 扩展类路径
*/
private Entry extClasspath;
/**
* 用户类路径
*/
private Entry userClasspath;
public ClassPath(String jreOption,String cpOption){
parseClasspath(jreOption,cpOption);
}
private void parseClasspath(String jreOption,String cpOption){
String jreDir = getJreDir(jreOption);
/**
* 启动类路径
*/
String jreLibPath = jreDir + "\\" + "lib" + "\\" + "*";
bootstrapClasspath = new WildcardEntry(jreLibPath);
/**
* 扩展类路径
*/
String jreExtPath = jreDir + "\\"+ "lib" + "\\" + "ext" +"\\"+"*";
extClasspath = new WildcardEntry(jreExtPath);
/**
* 用户类路径
*/
userClasspath = Entry.newEntry(cpOption);
}
/**
* //1优先使用用户输入的-Xjre选项作为jre目录
* //2当前目录下寻找jre目录
* //3用JAVA_HOME环境变量
* @param jreOption
* @return
*/
private String getJreDir(String jreOption){
File file;
/**
* 第一种情况
*/
if(jreOption != null && !"".equals(jreOption)){
file = new File(jreOption);
if(file.exists()){
return jreOption;
}
}
/**
* 第二种情况
*/
file = new File("jre");
if(file.exists()){
return file.getAbsolutePath();
}
/**
* 第三种情况
*/
if(System.getenv("JAVA_HOME") != null){
return System.getenv("JAVA_HOME")+"\\"+"jre";
}
/**
* 三种情况都不满足,抛出异常
*/
throw new RuntimeException("can not find jre folder!");
}
public byte[] readClass(String className){
/**
* 统一规范格式
*/
if(className.endsWith(".class")){
throw new RuntimeException("TypeError:" + className + "should be" + className.substring(0,className.length()-6));
}
className = className.replace(".","/") + ".class";
byte[] data;
try{
data = bootstrapClasspath.readClass(className);
if(data != null){
return data;
}
data = extClasspath.readClass(className);
if(data != null){
return data;
}
data = userClasspath.readClass(className);
if(data != null){
return data;
}
}catch (IOException e){
e.printStackTrace();
}
throw new RuntimeException("can't find class");
}
public String printAbsPath(){
return userClasspath.printAbsPath();
}
}
修改Main.java
import classpath.ClassPath;
import java.util.Arrays;
/**
* @ClassName Main
* @Description TODO
* @Author Mr.G
* @Date 2018/10/9 10:43
* @Version 1.0
*/
public class Main {
public static void main(String[] args){
Cmd cmd=new Cmd(args);
if(!cmd.isRightFmt||cmd.helpFlag){
cmd.printUsage();
}else if(cmd.versionFlag){
System.out.println("version 0.0.1");
}else{
startJVM(cmd);
}
}
public static void startJVM(Cmd cmd){
ClassPath cp = new ClassPath(cmd.getXjreOption(),cmd.getCpOption());
System.out.println("classpath:"+cp.printAbsPath()+" class:"+cmd.getClazz()+" args:"+cmd.args);
byte[] data=cp.readClass(cmd.getClazz());
System.out.println(Arrays.toString(data));
}
}
大功告成,运行