版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u013219624/article/details/89253881
1.基本介绍
JVM认为同一个类的2个条件,第一相同的类加载器引用,第二相同的名称(包名+类名)。也就是说,同一个.class文件被不同的类加载器加载,却不是相同的类。
2.自定义类加载器方式
- 如果不想打破双亲委派模型, 那么只需要重写findClass方法即可
- 如果想打破双亲委派模型,那么就重写整个loadClass方法
3.不打破双亲委派模型实现
public class CustomAClassLoader extends ClassLoader {
private String filePath = null;
protected synchronized Class<?> findClassByFilePathAndName(String filePath, String name)
throws ClassNotFoundException {
if (Objects.isNull(filePath) || Objects.isNull(name)) {
throw new IllegalArgumentException("参数不能为空");
}
this.filePath = filePath;
return findClass(name);
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(filePath)
.append(name.replace(".", "/"))
.append(".class");
FileInputStream fis = null;
ByteArrayOutputStream baos = null;
try {
baos = new ByteArrayOutputStream();
fis = new FileInputStream(new File(stringBuilder.toString()));
byte[] bytes = new byte[1024];
int len = -1;
while ((len = fis.read(bytes)) != -1) {
baos.write(bytes, 0, len);
}
return this.defineClass(name, baos.toByteArray(), 0, baos.size());
} catch (Exception e) {
throw new ClassNotFoundException();
} finally {
closeStream(fis);
closeStream(baos);
}
}
private void closeStream(InputStream stream) {
if (Objects.nonNull(stream)) {
try {
stream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void closeStream(OutputStream stream) {
if (Objects.nonNull(stream)) {
try {
stream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
4.自定义被加载的类
public interface IUserDao {
void save();
}
public class UserDao implements IUserDao {
@Override
public void save() {
System.out.println("save method.");
}
}
5.测试
public static void main(String[] args) throws Exception {
String name = "test.UserDao";
String filePath = "D:\\test\\target\\classes\\";
CustomAClassLoader classLoader = new CustomAClassLoader();
Class<IUserDao> userDaoClass = (Class<IUserDao>) classLoader.findClassByFilePathAndName(filePath, name);
IUserDao userDao = userDaoClass.newInstance();
userDao.save();
Class<IUserDao> appUserDaoClass = (Class<IUserDao>) ClassLoaderDemo.class.getClassLoader().loadClass(name);
IUserDao appUserDao = appUserDaoClass.newInstance();
appUserDao.save();
while (true) {
}
}
6.分析其在JVM中,存在几个class