可以看看下面这些文章,讲的很好
https://blog.csdn.net/codeyanbao/article/details/82875064
https://www.jianshu.com/p/1e4011617650
双亲委派机制
为什么要有双亲委派机制?(优点)?
防止重复加载.class
保证核心.class不会被篡改
打破了双亲委派的例子
Tomcat中的web 容器类加载器也是破坏了双亲委托模式的,自定义的WebApplicationClassLoader除了核心类库外,都是优先加载自己路径下的Class;
如果我们不想用双亲委派模型怎么办?(打破双亲委派)
为了避免双亲委托机制,我们可以自己定义一个类加载器,然后重写 loadClass() 即可。
原文
https://www.zhihu.com/question/45022217
步骤如下
(1)继承ClassLoader
(2)重写findClass()方法
(3)调用defineClass()方法下面写一个自定义类加载器:指定类加载路径在D盘下的lib文件夹下
新建立一个Test类
package com.test;
public class Test {
public void say(){
System.out.println("Hello MyClassLoader");
}
}
cmd控制台执行javac Test.java,将生成的Test.class文件放到D盘lib文件夹->com文件夹->test文件夹下;
自定义类加载器,代码如下:
package test;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
public class MyClassLoader extends ClassLoader
{
private String classpath;
public MyClassLoader(String classpath)
{
this.classpath = classpath;
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException
{
try
{
byte[] classDate = getClassBinaryData(name);
if (classDate == null)
{
}
else
{ // defineClass方法将字节码转化为类
return defineClass(name, classDate, 0, classDate.length);
}
}
catch (IOException e)
{
e.printStackTrace();
}
return super.findClass(name);
} // 返回类的字节码
private byte[] getClassBinaryData(String className) throws IOException
{
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 (FileNotFoundException e)
{
e.printStackTrace();
}
finally
{
in.close();
out.close();
}
return null;
}
}
测试代码:
package test;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class TestMyClassLoader
{
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException,
NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException
{ // 自定义类加载器的加载路径
MyClassLoader myClassLoader = new MyClassLoader("D:\\lib"); // 包名+类名
Class c = myClassLoader.loadClass("com.test.Test");
if (c != null)
{
Object obj = c.newInstance();
Method method = c.getMethod("say", null);
method.invoke(obj, null);
System.out.println(c.getClassLoader().toString());
}
}
}
![](https://pic1.zhimg.com/50/v2-9ab494514bdb773634b7bc70b69eea68_720w.jpg?source=1940ef5c)