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();出来的信息还是旧的,请问这是为什么?
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();出来的信息还是旧的,请问这是为什么?
同时在C:\\ClassA.jar文件中又有一个有包名com.my.test.loader的ClassA.class,
同时在主程序运行的当前目录下又有com\my\test\loader\目录,该目录下又有一个ClassA.class,您说JVM或javac该怎么办???
ClassA a = (ClassA) cls1.newInstance()会发生什么???
要么编译通不过,要么ClassCastException,要么ClassA都是上面三者中的同一个ClassA,
这种安全问题不需要您挖空心思去想了。
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.javaF:\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("-----------------------------------");
Class c = new ClassA().findClass("my.ClassA");
System.out.println("ClassLoader name: "+c.getClassLoader());
my.ClassA a = (my.ClassA) c.newInstance();
a.print();
} catch (Throwable e) {
e.printStackTrace();
}
try {
System.out.println("\r\n第四种方式:");
System.out.println("-----------------------------------");
URLClassLoader loader = new URLClassLoader(
new URL[] { classesDir.toURL() }, new ClassA());
Class c = loader.loadClass("my.ClassA");
System.out.println("ClassLoader name: "+c.getClassLoader());
my.ClassA a = (my.ClassA) c.newInstance();
a.print();
} catch (Throwable e) {
e.printStackTrace();
}
}
protected Class findClass(String className) throws ClassNotFoundException {
byte classData[]=null;
try {
String fileName=className.replace('.',File.separatorChar)+".class";
System.out.println("fileName: "+fileName);
FileInputStream fis = new FileInputStream(fileName);
BufferedInputStream bis = new BufferedInputStream(fis);
ByteArrayOutputStream out = new ByteArrayOutputStream();
int c = bis.read();
while (c != -1) {
out.write(c);
c = bis.read();
}
classData=out.toByteArray();
fis.close();bis.close();out.close();
} catch (Exception e) {
e.printStackTrace();
throw new ClassNotFoundException();
}
return defineClass(className, classData, 0, classData.length);
}
}
Class cls1 = loader1.loadClass("com.my.test.loader.ClassA");
载入的真是 "C:\ClassA.jar" 里的那个 class
ClassA a = (ClassA) cls1.newInstance();
就会发生 ClassCastException 了,因为它们虽然名字一样,却不是同一个东西。
ClassLoader parentLoader = ClassA.class.getClassLoader();
URLClassLoader loader1 = new URLClassLoader(
new URL[] { classesDir.toURL() }, parentLoader);
首先:parentLoader不用设,直接给个null强制让自己加载,而不是通过父loader加载。
Class cls1 = loader1.loadClass("com.my.test.loader.ClassA");
ClassA a = (ClassA) cls1.newInstance();
不能强制转换,因为转换的类不是你从URL中加载的类。所以这两行代码可以改为:
Method method = cls1.getMethod("print", null);
method.invoke(this, null); //this换成你自己的对象就可以了。
Test.javapackage test;import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;public class Test { public static void main(String[] args) throws Exception { ClassA.print();
File file = new File("C:/"); URL url = file.toURL();
URLClassLoader loader1 = new URLClassLoader(new URL[] { url }, null);
Class cls1 = loader1.loadClass("ClassA");
Method method = cls1.getMethod("print", null);
method.invoke(cls1.newInstance(), null);
}}ClassA.java(有包)package test;public class ClassA {
public static void print() {
System.out.println("This class is ClassA with pakage test.");
}
}ClassA.java(无包)public class ClassA {
public static void print() {
System.out.println("This class is ClassA that hasn't pakage.");
}
}
输出:
This class is ClassA with pakage test.
This class is ClassA that hasn't pakage.