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

Java面试问题之十三
类加载器是Java虚拟机中重要的部分,请自定义一个类加载器来实现.class文件的加载功能。

答:要创建一个用户自己的类加载器,只需要扩展java.lang.ClassLoader类,然后覆盖它的findClass(String name)方法即可,该方法根据参数指定了类的名称,返回对应Class对象的引用。下面编写一个MyClassLoader来实现.class文件的加载功能。



import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

public class MyClassLoader extends ClassLoader{
         private String name;
         private String path="d:\\";
         private final String fileType=".class";

         public MyClassLoader(String name){
                super();
                this.name=name;
         }

         public MyClassLoader(ClassLoader parent,String name){
                 super(parent);
                 this.name=name;
         }

         public String toString(){
                return  name;
         }


         //设定类类文件所在的路径
         public void setPath(String path){
                 this.path=path;
         }

         public String getPath(){
                 return this.path;
         }

         //findClass需要被覆盖,定义自己的逻辑供系统调用
         protected Class findClass(String name) throws ClassNotFoundException{
               byte[] data= loadClassData(name);
               return defineClass(name,data,0,data.length);        //返回对应的Class引用 
        }

        private byte[] loadClassData(String name) throws ClassNotFoundException{
               FileInputStream fis=null;
               byte[] data=null;
               ByteArrayOutputStream baos=null;

               try{
                        name=name.replaceAll("\\.","\\\\");
                        fis=new FileInputStream(new File(path+name+fileType));
                        baos=new ByteArrayOutputStream();

                        int ch=0;        
                        while((ch=fis.read())!=-1){
                                baos.write(ch);              //将.class文件写入内存中
                        }

                        data=baos.toByteArray();
    
               }catch(IOException e){
                     throw new ClassNotFoundException("Class is not found:"+name,e);
               }finally{
                     //注意:在最后一定要关闭输入输出流对象
                    try{ 
                           fis.close();
                           baos.close();
                    }catch(IOException e) {
                            e.printStackTrace();
                    }
               }

              return data;

        }

        public static void test(ClassLoader loader) throws Exception {
                Class objClass = loader.loadClass("Sample");
                Object obj=objClass.newInstance();    //创建一个Sample类实例
        }
         

        public static void main(String[] args){
               try{
                      MyClassLoader loader1=new MyClassLoader("loader1");
                      loader1.setPath("D:\\Java\\Program\\Exercises");
                      MyClassLoader loader2=new MyClassLoader(loader1,"loader2");
                      loader2.setPath("D:\\Java\\Program\\Exercises");

                      MyClassLoader loader3=new MyClassLoader(null,"loader3");
                      loader3.setPath("D:\\Java\Program\\Others");

                      test(loader2);
                      test(loader3);


               }catch(Exception e){
                     e.printStackTrace();
               }
        }

}




此类中的私有方法loadClassData(String name)根据参数指定的类的名称,把相应的.class文件的二进制数据读入到内存中,并且以字节数组的形式返回。