直接看如下错误例子
com.hotload.Test cannot be cast to com.hotload.Test,因为com.hotload.Test
的类加载器是MyComOtherClassLoader
,而非默认的 sun.misc.Launcher$AppClassLoader
如下则正常
关于解决办法,比如可以通过序列化/反序列化解决转换,如下
附自定义的classloader
package com.hotload;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class MyComOtherClassLoader extends ClassLoader {
public String path;
public String packageName;
public String className;
public MyComOtherClassLoader() {
super(ClassLoader.getSystemClassLoader());
}
private String classNameToPath() {
// 得到类文件的URL
return path + "/" + packageName.replace('.', '/')
+ "/"
+ className + ".class";
}
@Override
public Class loadClass(String name) throws ClassNotFoundException {
// 非 com.hotload package下面的类,都用默认的加载,否则用自定义的加载方法
if (!name.contains("com.hotload")) {
// 是否已经被加载
Class loadedClass = findLoadedClass(name);
if (loadedClass == null) {
// 用父类去加载该类
loadedClass = getParent().loadClass(name);
return loadedClass;
} else {
return loadedClass;
}
}
int i = name.lastIndexOf('.');
packageName = "";
if (i != -1) {
packageName = name.substring(0, i);
// System.out.println("package: " + packageName);
className = name.substring(i + 1);
// System.out.println("class name: " + name);
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPackageAccess(packageName);
}
}
//依然调用父类的方法
// return super.loadClass(name);
return this.findClass(name);
}
@Override
public Class<?> findClass(String name) throws ClassNotFoundException {
int i = name.lastIndexOf('.');
packageName = "";
if (i != -1) {
packageName = name.substring(0, i);
// System.out.println("package: " + packageName);
className = name.substring(i + 1);
// System.out.println("class name: " + name);
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPackageAccess(packageName);
}
}
Class<?> clazz = this.findLoadedClass(name); // 父类已加载
if(null != clazz){
return clazz;
}
// System.out.println("findClass param name: " + name);
byte [] b = this.getClassBytes();
// System.out.println("b len:" + b.length);
clazz=defineClass(null, b, 0, b.length);
return clazz;
}
public byte[] getClassBytes() {
String classPath = classNameToPath();
// System.out.println("classPath:" + classPath);
File file=new File(classPath);
try(FileInputStream fis = new FileInputStream(file);ByteArrayOutputStream bos=new ByteArrayOutputStream();) {
byte[] b=new byte[1024*2];
int n;
while((n=fis.read(b))!=-1){
bos.write(b, 0, n);
}
return bos.toByteArray();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}