package com.coderising.jvm.loader; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.util.ArrayList; import java.util.List; import com.coderising.jvm.clz.ClassFile; public class ClassFileLoader { private static final int BUFFERSIZE = 1024; private List<String> clzPaths = new ArrayList<String>(); /** * 装载class文件 * 读取二进制字节流,并解析成ClassFile对象 * @param className * @return ClassFile */ public ClassFile loadClass(String className) { byte[] codes = this.readBinaryCode(className); ClassFileParser parser = new ClassFileParser(); return parser.parse(codes); } /** * 从.class文件读取二进制字节流 * @param className * @return */ public byte[] readBinaryCode(String className) { if (clzPaths.size()<=0){ return null; } for (int i = 0; i < clzPaths.size(); i++) { String path = clzPaths.get(i) + convertName(className); File f = new File(path); if(f.exists()){ try { return readFile(f); } catch (FileNotFoundException e) { e.printStackTrace(); } }else{ f = null; continue; } } System.err.println("classpath:" +getClassPath()+ "class:" + convertName(className)+" not found."); return null; } /** * 文件读取二进制字节流 * @param f * @return byte[] * @throws FileNotFoundException */ private byte[] readFile(File f) throws FileNotFoundException { FileInputStream fis = new FileInputStream(f); ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] b = new byte[BUFFERSIZE]; try { int len = 0; while((len = fis.read(b))!=-1){ baos.write(b,0,len); } } catch (IOException e) { e.printStackTrace(); } finally{ try { fis.close(); baos.flush(); baos.close(); } catch (IOException e) { e.printStackTrace(); } } return baos.toByteArray(); } /** * 增加类加载路径,加载时按增加时的先后顺序加载 * @param path */ public void addClassPath(String path) { clzPaths.add(path); } /** * 获取类加载路径 * @return */ public String getClassPath() { StringBuilder sb = new StringBuilder(); for (int i = 0; i < clzPaths.size(); i++) { sb.append(clzPaths.get(i)).append(";"); } int len = sb.length(); if(len!=0){ sb.deleteCharAt(len-1); } return sb.toString(); } /** * convert className to FilePath style className <br/> * For example:com.sun.lang to \com\sun\lang * * @param className * @return FilePath style className */ private String convertName(String className) { StringBuilder sb = new StringBuilder(); String[] pack = className.split("\\."); for (int i = 0; i < pack.length; i++) { sb.append("\\").append(pack[i]); } sb.append(".class"); return sb.toString(); } }