日期:2014-05-20  浏览次数:21006 次

ClassLoader 问题,请Java的大内高手帮帮忙!!!
public   void   testLoaderDiffJar()   throws   ClassNotFoundException,   MalformedURLException,   InstantiationException,   IllegalAccessException   {

    ClassA   orgA   =   new   ClassA();
    orgA.print();

    File   classesDir   =   new   File( "C:\\ClassA.jar ");

    ClassLoader   parentLoader   =   ClassA.class.getClassLoader();
    URLClassLoader   loader1   =   new   URLClassLoader(
        new   URL[]   {   classesDir.toURL()   },   parentLoader);
    Class   cls1   =   loader1.loadClass( "com.my.test.loader.ClassA ");
    ClassA   a   =   (ClassA)   cls1.newInstance();
    a.print();
}

----------------
问题:ClassLoader上来的类并没有替换原先的类。a.print();出来的信息还是旧的,请问这是为什么?

------解决方案--------------------
你没有明白 ClassLoader的 运行机制

ClassLoader在加载类的时候回首先把请求委托给它的父loader(也就是 你代码中的parentLoader ) 去加载

所以你的URLClassLoader在加载 ClassA的时候 会调用自己的父Loader 去加载

而这是 ClassA 已经被记载了,因为你前面的代码有ClassA 的操作

所以就出现了这种情况

要达到你的目的,要将 URLClassLoader 的机制改写一下 不让它委托加载

在defineClass(方法名我记不清出了)里面可以改写 你自己试试

不明白再交流
------解决方案--------------------
/*
JDK版本:jdk1.4.2与jdk1.6.0

目录文件位置:
F:\csdn\20070129\ClassA.class
F:\csdn\20070129\ClassA.java
F:\csdn\20070129\ClassA.jar
F:\csdn\20070129\my\ClassA.class
F:\csdn\20070129\my\ClassA.java

F:\csdn\20070129\ClassA.jar文件内容:
my\ClassA.class
my\ClassA.java


编译: F:\csdn\20070129> javac ClassA.java my\ClassA.java
打包: F:\csdn\20070129> jar -cvf ClassA.jar my
运行: F:\csdn\20070129> java ClassA
结果: 请猜一下????????能用双亲委派的原理分析出正确结果吗?????????

最后: 试试在getClassLoader()后加“.getParent()”看看结果如何?????????
试试在ClassA前加“my.”看看结果又是如何?????????
*/


//F:\csdn\20070129\my\ClassA.java源码
package my;
public class ClassA{
public void print() {
System.out.println( "my HACK ClassA ");
}
}

//F:\csdn\20070129\ClassA.java源码
import java.net.*;
import java.io.*;
public class ClassA extends ClassLoader {
public void print() {
System.out.println( "my ClassA ");
}

public static void main(String[] args) {
System.out.println( "第一种方式: ");
System.out.println( "----------------------------------- ");
ClassA orgA = new ClassA();
orgA.print();
System.out.println( "ClassLoader name: "+ClassA.class.getClassLoader());

File classesDir = new File( "ClassA.jar ");

try {
System.out.println( "\r\n第二种方式: ");
System.out.println( "----------------------------------- ");
ClassLoader parentLoader = ClassA.class.getClassLoader();
URLClassLoader loader = new URLClassLoader(
new URL[] { classesDir.toURL() }, parentLoader);
Class c = loader.loadClass( "my.ClassA ");
System.out.println( "ClassLoader name: "+c.getClassLoader());
ClassA a = (ClassA) c.newInstance();
a.print();
} catch (Throwable e) {
e.printStackTrace();
}

try {
System.out.println( "\r\n第三种方式: ");
System.out.println( "----------------------------------- ");