自定义类加载器与热部署

一、自定义类加载器

要创建用户自己的类加载器,只需要继承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,这样就能控制类加载的时机,从而实现热部署。

热部署步骤:

  1. 销毁自定义的classloader(被该加载器加载的class也会自动卸载)
  2. 更新class
  3. 使用新的ClassLoader去加载class

你可能感兴趣的:(java面试)