在加载类别时,每个类别加载器会先将加载类别的任务交由其parent,如果parent找不到,才由自己负责加载,如果自己也找不到,就会丢出 NoClassDefFoundError。
-
启动类加载器 bootstarpClassLoader
加载范围 jdk lib -
扩展类加载器 extensionClassLoader
-
应用类加载器 appClassLoader
加载范围 classPath
public class ClassLoaderStudy {
/***
* 在加载类别时,每个类别加载器会先将加载类别的任务交由其parent,
* 如果parent找不到,才由自己负责加载,如果自己也找不到,就会丢出 NoClassDefFoundError。
* @param args
* @throws ClassNotFoundException
*/
public static void main(String[] args) throws ClassNotFoundException {
/***
* 启动类加载器 bootstrapClassLoader
*
* 加载范围
*
*/
System.out.println(String.class.getClassLoader());
/***
* 扩展类加载器 ExtensionClassLoader
*
* 加载范围
*
*/
Class<?> driver = Class.forName("java.sql.Driver");
System.out.println(driver.getClassLoader());
/***
* 应用类加载器 AppClassLoader
*
* 加载范围 classpath
*
*/
System.out.println(DatatypeException.class.getClassLoader());
System.out.println(System.getProperty("sun.boot.class.path"));
System.out.println(System.getProperty("java.ext.dirs"));
System.out.println(System.getProperty("java.class.path"));
}
}
- 自定义类加载器(加载非classpath下的类)
public class Main {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException,
InvocationTargetException {
//设置加载路径
MyClassLoader myClassLoader = new MyClassLoader("D:\\项目\\TBTX\\TX_JLM\\target\\classes\\");
//查找指定类
Class<?> clz = myClassLoader.findClass("com.wcn.xxx.server.XxServer");
System.out.println(clz.getName());
//获取指定类实例
Object obj = clz.newInstance();
//遍历调用方法
Method[] methods = clz.getDeclaredMethods();
for (Method method : methods) {
method.invoke(obj, args);
}
}
}
class MyClassLoader extends ClassLoader {
private String path;
MyClassLoader(String path) {
this.path = path;
}
@Override
protected Class<?> findClass(String name) {
File file = new File(this.path + name.replaceAll("\\.", "/") + ".class");
byte[] bytes = new byte[0];
try {
//将class文件读入字节数据中
bytes = getClassBytes(file);
} catch (Exception ee) {
ee.printStackTrace();
}
//写入内存返回Class对象
return this.defineClass(name, bytes, 0, bytes.length);
}
private byte[] getClassBytes(File file) throws Exception {
// 这里要读入.class的字节,因此要使用字节流
FileInputStream fis = new FileInputStream(file);
FileChannel fc = fis.getChannel();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
WritableByteChannel wbc = Channels.newChannel(baos);
ByteBuffer by = ByteBuffer.allocate(1024);
while (true) {
int i = fc.read(by);
if (i == 0 || i == -1) { break; }
by.flip();
wbc.write(by);
by.clear();
}
fis.close();
return baos.toByteArray();
}
}
网友评论