一、自定义类加载器
要创建用户自己的类加载器,只需要继承java.lang.ClassLoader类,然后覆盖它的findClass(String name)方法即可,即指明如何获取类的字节码流。
如果要符和双亲委派规范,则重写findclass方法(用户自定义类加载逻辑);要破坏的话,重写loadclass方法(双亲委派的具体逻辑实现)。
例子:
package classloader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
class TestClassLoad {
@Override
public String toString() {
return "类加载成功。";
}
}
public class PathClassLoader extends ClassLoader {
private String classPath;
public PathClassLoader(String classPath) {
this.classPath = classPath;
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
byte[] classData = getData(name);
if (classData == null) {
throw new ClassNotFoundException();
} else {
return defineClass(name, classData, 0, classData.length);
}
}
private byte[] getData(String className) {
String path = classPath + File.separatorChar
+ className.replace('.', File.separatorChar) + ".class";
try {
InputStream is = new FileInputStream(path);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
byte[] buffer = new byte[2048];
int num = 0;
while ((num = is.read(buffer)) != -1) {
stream.write(buffer, 0, num);
}
return stream.toByteArray();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public static void main(String args[]) throws ClassNotFoundException,
InstantiationException, IllegalAccessException {
ClassLoader pcl = new PathClassLoader("D:\\ProgramFiles\\eclipseNew\\workspace\\cp-lib\\bin");
Class c = pcl.loadClass("classloader.TestClassLoad");//注意要包括包名
System.out.println(c.newInstance());//打印类加载成功.
}
}
二、Java热部署实现
热部署是在不重启Java虚拟机的前提下,能自动侦测到class文件的变化,更新运行时class的行为,Java类是通过Java虚拟机加载的,某个类的class文件在被classloader加载后,会生成对应的Class对象,之后就可以创建该类的实例。默认的虚拟机行为只会在启动时加载类,如果后期有一个类需要更新的话,单纯替换编译的class文件,Java虚拟机是不会更新正在运行的class。如果要实现热部署,最根本的方法是修改虚拟机的源代码,改变classloader的加载行为,使虚拟机能监听class文件的更新,重新加载class文件,这样的行为破坏性很大,为后续的JVM升级埋下了一个大坑。
更一种友好的方法是创建自己的classloader来加载需要监听的class,这样就能控制类加载的时机,从而实现热部署。
热部署步骤:
- 销毁自定义的classloader(被该加载器加载的class也会自动卸载)
- 更新class
- 使用新的ClassLoader去加载class