【问题标题】:Reload class which is loaded using custom classloader重新加载使用自定义类加载器加载的类
【发布时间】:2017-12-15 13:49:08
【问题描述】:

以下是我的自定义类加载器类。我使用以下 javaargs 将其设置为默认类加载器。

-Djava.system.class.loader=MyCustomClassLoader

import java.io.*;
public class MyCustomClassLoader extends ClassLoader { 
    public MyCustomClassLoader() { super(); } 
    public MyCustomClassLoader(ClassLoader parent) { super(parent); } 
    protected Class loadClass(String name, boolean resolve ) throws ClassNotFoundException { 
        Class c = super.loadClass(name, resolve ); 
        System.out.println( "name: " + name + ", class: " + c); 
        return c; 
    }
}

此时,当我启动服务器时,所有类都使用上述自定义类加载器类加载。我希望按需更新/重新加载属于特定包(例如 com.test)的类的类定义。我该怎么做?

【问题讨论】:

    标签: java jvm classloader


    【解决方案1】:

    你应该做一个类加载器,它会自己加载客户类,不要让超级加载它们。试试我的例子,它可能有助于理解

    package test;
    import java.io.IOException;
    import java.net.MalformedURLException;
    import java.nio.file.Files;
    import java.nio.file.Paths;
    import java.util.HashMap;
    import java.util.Map;
    
    class MyClassLoader extends ClassLoader {
        private Map<String, Class<?>> loadedClasses = new HashMap<>();
        private String dir;
    
        public MyClassLoader(String dir) throws MalformedURLException {
            this.dir = dir;
        }
    
        protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
            Class<?> c = findLoadedClass(name);
            if (c != null) {
                return c;
            }
            c = loadedClasses.get(name);
            if (c != null) {
                return c;
            }
            try {
                String path = dir + name.replace(".","/") + ".class";
                byte[] bytes = Files.readAllBytes(Paths.get(path)); 
                c = defineClass(name, bytes, 0, bytes.length, null);
                if (resolve) {
                    resolveClass(c);
                }
                return c;
            } catch (IOException ex) {
                return super.loadClass(name, resolve);
            }
        }
    }
    
    public class ChildFirstClassLoader {
    
        public static void main(String[] args) throws Exception {
            ClassLoader cl1 = new MyClassLoader("target/classes/");
            Object x1 = cl1.loadClass("test.X1").newInstance();
            System.out.println(x1.getClass().getClassLoader());
            cl1 = null;
    
            ClassLoader cl2 = new MyClassLoader("target/classes/");
            x1 = cl2.loadClass("test.X1").newInstance();
            System.out.println(x1.getClass().getClassLoader());
    
        }
    }
    

    【讨论】:

    • 与现有的URLClassLoader 相比,MyClassLoader 没有任何优势。您回答的关键点是您正在创建两个类加载器实例,因为在单个类加载器中重新加载类不起作用。我建议专注于这一点,而不是使用冗余的类加载器实现分散相关点。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多