使用自定义类加载器重新加载类

时间:2015-03-16 17:49:55

标签: java

我正计划使用自定义类加载器进行类的热部署。对于此任务,我编写了自定义类加载器。看起来像

public class CustomClassLoader extends ClassLoader{
        public CustomClassLoader(ClassLoader parent) {
            super(parent);
        }
        public Class loadClass(String name) throws ClassNotFoundException {
            if(!"classLoader.TestCase".equals(name))
                    return super.loadClass(name);
            try {
                String url = null;
                String clzName = null;
                url = "file:/home/naveen/workspace/JavaConcept/bin/classLoader/TestCase.class";
                    clzName = "classLoader.TestCase";
                }
                URL myUrl = new URL(url);
                URLConnection connection = myUrl.openConnection();
                InputStream input = connection.getInputStream();
                ByteArrayOutputStream buffer = new ByteArrayOutputStream();
                int data = input.read();
             while(data != -1){
                    buffer.write(data);
                    data = input.read();
                }
                input.close();
                byte[] classData = buffer.toByteArray();
           return defineClass(clzName,classData, 0, classData.length);
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        return null;
        }
}

现在我有另一个名为TestCase的类,它有一个名为print()的方法。

public void print(){
        System.out.println("Hello");
        System.out.println("Bye");
    }

我正在使用类似这样的主要方法调用它

public static void main(String arg[]) throws InstantiationException, IllegalAccessException{

        TestCase t = new TestCase();
        t.print();

        try {
            ClassLoader classLoader = CustomClassLoader.class.getClassLoader(); 
            classLoader = new CustomClassLoader(classLoader);
            Class clz = classLoader.loadClass("classLoader.TestCase");
            TestCase t2 = new TestCase();
            t2.print();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

现在我想在一个主要的t.print()方法中做一件事,它在控制台上打印hello和bye。现在我有一个这个Testcase类的打印方法的另一个版本,它只打印Hello。所以我做了什么,我在调试模式下声明了程序,让程序继续,直到classLoader.loadClass()行。然后我用目录结构替换了Testcase.class,新版本只打印hello.But仍显示输出Hello和Bye。 有人可以帮我解决这个程序有什么问题,或者我对类加载器的理解不正确。请纠正我并帮助完成我的任务。

1 个答案:

答案 0 :(得分:0)

自定义类加载器很难实现,因为您需要记住许多规则。在你的情况下,我想问题是你的类文件是程序的一部分,这意味着如果你尝试加载一个类,默认的类加载器将在调用永远不会被调用的loadClass()方法之前加载它。尝试从类路径中删除类文件,使其不属于您的程序,然后调用loadClass()。

第二个问题是你正在使用new创建你的TestCase对象,它将调用默认的类加载器,更好的方法是调用classLoader.loadClass()然后从返回的类创建一个实例,但是如果你强制转换到TestCase,这意味着在默认的类加载器中定义了类,这导致了第一个问题。另一种方法是创建一个接口并强制转换为该接口,以便调用您的方法。