转https://blog.csdn.net/zhoudaxia/article/details/35824249
ClassLoader.loadClass(...) 是ClassLoader的入口点。当一个类没有指明用什么加载器加载的时候,JVM默认采用AppClassLoader加载器加载没有加载过的class,调用的方法的入口就是loadClass(...)。如果一个class被自定义的ClassLoader加载,那么JVM也会自动调用这个自定义的ClassLoader.loadClass(...)方法来加载class内部引用的一些别的class文件。
仿照Tomcat的类加载器写了一个加载器,不采用双亲委派,首先加载自己定义的类路径下的类,加载不到再让父加载器加载。
调用MyClassLoader
类加载器来加载类BootClass
,则BootClass
中所有引用到的类jvm都会自动使用加载BootClass
的类加载器MyClassLoader.loadClass
来加载,而且这不是通过Thread.currentThread().setContextClassLoader()
来实现的。》

MyClassLoader
package com.dongnao.TestClassloader;
import java.io.*;
public class MyClassLoader extends ClassLoader{
private String classpath;
public MyClassLoader(String classpath) {
this.classpath = classpath;
}
/**
* Jvm自动调用
* 1.从手动设置的classpath路径加载
* 2.如果没有加载到则从parent加载
* @param name
* @return
* @throws ClassNotFoundException
*/
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
System.out.println("--------------------loading "+name+"------------------");
Class<?> aClass = findLoadedClass(name);
if (aClass!=null){
//System.out.println("-----Have loaded-----");
return aClass;
}
aClass = findClass(name);
if (aClass==null&&getParent()!=null){
//System.out.println("------Give parent-----");
aClass = getParent().loadClass(name);
}
//System.out.println("-------------Finish "+aClass+"---------------");
return aClass;
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
byte [] classData=getData(name);
if(classData==null) {
return null;
}else {
//defineClass方法将字节码转化为类
return defineClass(name,classData,0,classData.length);
}
}
//返回类的字节码
private byte[] getData(String className){
InputStream in = null;
ByteArrayOutputStream out = null;
String path=classpath + File.separatorChar +
className.replace('.',File.separatorChar)+".class";
try {
in=new FileInputStream(path);
out=new ByteArrayOutputStream();
byte[] buffer=new byte[2048];
int len=0;
while((len=in.read(buffer))!=-1){
out.write(buffer,0,len);
}
return out.toByteArray();
}
catch (IOException e) {
}
finally{
try {
if (in!=null)
in.close();
} catch (IOException e) {
//e.printStackTrace();
}
try {
if (out!=null)
out.close();
} catch (IOException e) {
//e.printStackTrace();
}
}
return null;
}
}
TestClassLoader
package com.dongnao.TestClassloader;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class TestClassLoader {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
System.out.println("Bootstrap ClassLoader:"+ClassLoader.getSystemClassLoader().getParent().getParent());
System.out.println("Extension ClassLoader:"+ClassLoader.getSystemClassLoader().getParent());
System.out.println("java.ext.dirs"+System.getProperty("java.ext.dirs"));
System.out.println("Application ClassLoader:"+ClassLoader.getSystemClassLoader());
System.out.println("java.class.path:"+System.getProperty("java.class.path"));
MyClassLoader myClassLoader = new MyClassLoader("out/production/basicsDemo/");
//调用MyClassLoader类加载器来加载类BootClass,
//则BootClass中所有引用到的类jvm都会自动使用BootClass的类加载器MyClassLoader.loadClass来加载
Class<?> testCase = myClassLoader.loadClass("com.dongnao.TestClassloader.App.BootClass");
Method startMethod = testCase.getMethod("start", null);
Object o = testCase.newInstance();
startMethod.invoke(o,null);
}
}
Reuslt
Bootstrap ClassLoader:null
Extension ClassLoader:sun.misc.Launcher$ExtClassLoader@1055e4af
java.ext.dirs:S:\Java\jre\lib\ext;C:\WINDOWS\Sun\Java\lib\ext
Application ClassLoader:sun.misc.Launcher$AppClassLoader@18b4aac2
java.class.path:S:\Java\jre\lib\charsets.jar;S:\Java\jre\lib\deploy.jar;S:\Java\jre\lib\ext\access-bridge-64.jar;S:\Java\jre\lib\ext\cldrdata.jar;S:\Java\jre\lib\ext\dnsns.jar;S:\Java\jre\lib\ext\jaccess.jar;S:\Java\jre\lib\ext\jfxrt.jar;S:\Java\jre\lib\ext\localedata.jar;S:\Java\jre\lib\ext\nashorn.jar;S:\Java\jre\lib\ext\sunec.jar;S:\Java\jre\lib\ext\sunjce_provider.jar;S:\Java\jre\lib\ext\sunmscapi.jar;S:\Java\jre\lib\ext\sunpkcs11.jar;S:\Java\jre\lib\ext\zipfs.jar;S:\Java\jre\lib\javaws.jar;S:\Java\jre\lib\jce.jar;S:\Java\jre\lib\jfr.jar;S:\Java\jre\lib\jfxswt.jar;S:\Java\jre\lib\jsse.jar;S:\Java\jre\lib\management-agent.jar;S:\Java\jre\lib\plugin.jar;S:\Java\jre\lib\resources.jar;S:\Java\jre\lib\rt.jar;H:\动脑Java\高并发分布式(专题三)\052-面试专题(Java基础)-20180206-Five\basicsDemo\out\production\basicsDemo;C:\Program Files\JetBrains\IntelliJ IDEA 2018.2.3\lib\idea_rt.jar;C:\Users\pengyunlong\.IntelliJIdea2018.2\system\captureAgent\debugger-agent.jar
--------------------loading com.dongnao.TestClassloader.App.BootClass------------------
--------------------loading java.lang.Object------------------
--------------------loading java.lang.System------------------
--------------------loading java.lang.StringBuilder------------------
--------------------loading java.lang.Class------------------
--------------------loading java.io.PrintStream------------------
BootClass:com.dongnao.TestClassloader.MyClassLoader
--------------------loading com.dongnao.TestClassloader.App.Biz------------------
>>>>>>>>>>>>>>>>>>>ClassLoaderInfo<<<<<<<<<<<<<<<<<<<<<<
Biz:com.dongnao.TestClassloader.MyClassLoader
Object:null
--------------------loading java.lang.Thread------------------
ContextClassLoader:sun.misc.Launcher$AppClassLoader
--------------------loading com.dongnao.TestClassloader.App.User------------------
Hello,my name is Bob
User:com.dongnao.TestClassloader.MyClassLoader@e6ea0c6
package com.dongnao.TestClassloader.App;
public class BootClass {
public void start(){
System.out.println("BootClass:"+this.getClass().getClassLoader().getClass().getName());
new Biz().echo();
}
}
package com.dongnao.TestClassloader.App;
public class Biz {
public void echo(){
System.out.println(">>>>>>>>>>>>>>>>>>>ClassLoaderInfo<<<<<<<<<<<<<<<<<<<<<<");
System.out.println("Biz:"+this.getClass().getClassLoader().getClass().getName());
System.out.println("Object:"+new Object().getClass().getClassLoader());
System.out.println("ContextClassLoader:"+Thread.currentThread().getContextClassLoader().getClass().getName());
User user = new User("Bob",10);
user.sayHello();
System.out.println("User:"+user.getClass().getClassLoader());
}
}
package com.dongnao.TestClassloader.App;
public class User {
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
public void sayHello(){
System.out.println("Hello,my name is "+name);
}
}
网友评论