Java的动态性很重要的原因是他提供了一种自定义的类的加载机制。 为了深入学习, 自己编写了一个自定义的类加载器类:主要的问题:
 疑问:1。 为什么我自定了加载类还没加载 系统的加载器就可以发现类的存在。 
       2。 可是在第二个输出信息中为什么又变成了 我自定义的加载器
       3。 更奇怪的是当我再次new 又会由系统加载器再次进行加载。
package classLaoder;
import java.io.*;
public class UserClassLoader extends ClassLoader {



public synchronized Class loadClass(String className, Boolean flag ) throws ClassNotFoundException {

//check the class weather  had been loaded
Class class1=null; //= Class.forName(className);
if(class1!= null)
System.out.println(class1.toString());
//return class1;

// check the class has not been loaded by the System ClassLoader

try{
class1 = super.findSystemClass(className);
if(class1!=null)
System.out.println(class1.toString());
}catch(ClassNotFoundException _ex){
System.out.println(">> Not a system class.");
}
byte abyte0[] = getClassBytes(className);
if(abyte0 == null){
throw new ClassNotFoundException();
}

class1 = defineClass(null, abyte0, 0, abyte0.length);
if(class1 == null){
throw new ClassFormatError();
}

if(flag){
resolveClass(class1);
}
System.out.println(">> Returning newly loaded class.");
return class1;


private byte[] getClassBytes(String className){
String path="D://Program//NASA Program//ClassLoaderTest//classLaoder//";
className=path+"UserClass.class";
File f=new File( className );
byte[] b = new byte[(int)f.length()];
 
 try{
 InputStream input= new FileInputStream( f );
 input.read(b);
 System.out.println(b);
 }catch(IOException e){
 e.printStackTrace();
 }
return b;
}
} 接着编写了一个测试程序:
package classLaoder;public class ClassLoaderTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
UserClassLoader loader= new UserClassLoader();
Object ob;
try{
ob=loader.loadClass("classLaoder.UserClass", true).newInstance();
System.out.println("the class UserClass is loader by  "+ob.getClass().getClassLoader() );
}catch(Exception e){
e.printStackTrace();
}
UserClass user=new UserClass();
System.out.println("now the class UserClass is loader by  "+user.getClass().getClassLoader() );
}
}
(其中的 UserClass 用于测试的一个非常简单的自定义的类)测试的结果:
class classLaoder.UserClass
[B@addbf1
>> Returning newly loaded class.
the class UserClass is loader by  classLaoder.UserClassLoader@42e816
now the class UserClass is loader by  sun.misc.Launcher$AppClassLoader@11b86e7疑问:1。 为什么我自定了加载类还没加载 系统的加载器就可以发现类的存在。 
      2。 可是在第二个输出信息中为什么又变成了 我自定义的加载器
      3。 更奇怪的是当我再次new 又会由系统加载器再次进行加载。

解决方案 »

  1.   

    UserClass user=new UserClass();你这句话已经要求JVM以当前线程的ClassLoader加载UserClass并实例化它
    JVM并没有要求一个类只加载一次,你在自定义ClassLoader加载了UserClass并不会影响其它的ClassLoader,所以后面还是看到了系统的ClassLoader
    一般来说,如果要用到自己的ClassLoader,最好是在你调用代码中全部使用Interface或者Abstract Class,真正的实现类依赖自己的ClassLoader加载,但是在后续代码中并不直接看到实现类,而是看到接口,这样就可以方便控制怎样加载自己的类,又不会再现系统自动加载你类的问题
      

  2.   

    谢谢楼上的解答, 我是刚开始学习这部分东西。  我按照你的做法, 给UserClass加了相应的接口但是系统还是自动加载了他。  我想问一下类的加载是什么时候发生的? 
        另外还有, 如果一个类可以被多次加载,  那么不是很不安全, 如果在两次加载中间有个线程改了类的一些属性, 那么JVM中就有了两个版本的类  这时候如何生成新的对象?
      

  3.   

    给UserClass增加接口后,系统自动加载的只是接口部分,这个是相对固定的部分,所以让系统加载是没有问题的只有实现类才是由你自己控制加载方式 
    当然你也可以Thread.currentThread().setContextClassLoader(cl)方式指定当前线程的ClassLoader