java类加载器

来源:互联网 发布:人教版电子书课本软件 编辑:程序博客网 时间:2024/05/14 11:09

看了看Spring源码,里面用到了ClassLoader。比如ClassPathResource里就用到了,所以现在系统地说明一下,下面给出个例子程序
<pre name="code" class="java">public class ClassLoaderDemo {


    public static void main(String[] args) {
        Class c;
        ClassLoader cl;
        //获取系统类加载器
        cl = ClassLoader.getSystemClassLoader();


        System.out.println(&quot;系统类加载器是 &quot; + cl);


       //获取委托的父类加载器是
        cl = cl.getParent();


        System.out.println(&quot;委托的父类加载器是&quot; + cl);


        try {


            c = Class.forName(&quot;java.lang.Object&quot;);


            cl = c.getClassLoader();


            System.out.println(&quot;Object类的加载器&quot; + cl);


            c = Class.forName(&quot;arthur.java.fromInternet.ClassLoaderDemo&quot;);


            cl = c.getClassLoader();


            System.out.println(&quot;本类的加载器是&quot; + cl);


        } catch (Exception e) {


            e.printStackTrace();


        }
    }
}
</pre>
运行结果如下
系统类加载器是 sun.misc.Launcher$AppClassLoader@19821f
委托的父类加载器是sun.misc.Launcher$ExtClassLoader@addbf1
Object类的加载器null
本类的加载器是sun.misc.Launcher$AppClassLoader@19821f


类加载器可以分为三种,一类是启动类加载器(Bootstrap  ClassLoader),一类是扩展类加载器(Extension ClassLoader),这个加载器由sun.misc.Launcher$ExtClassLoader来实现,上面的委托的父类加载器就是这个类型,还有一类是应用程序加载器,由sun.misc.Launcher$AppClassLoader类实现,可以对照上面的运行结果看看各自属于哪个加载器




三个加载器的关系可以如下表示:启动类加载器<---扩展类加载器<---应用程序类加载器,注意这不是继承关系而是组合关系
下面看看加载类的实现方法以及加载过程
  protected synchronized Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
    {
//首先检查是否已经被加载过,
Class c = findLoadedClass(name);
if (c == null) {//如果没有则调用父加载器
   try {
if (parent != null) {
   c = parent.loadClass(name, false);
} else {//如果父加载为空则使用默认的启动类加载器作为父加载器
   c = findBootstrapClassOrNull(name);
}
   } catch (ClassNotFoundException e) {
                // ClassNotFoundException thrown if class not found
                // from the non-null parent class loader
            }
            if (c == null) {
       //如果以上加载失败,就使用自己的findClass()方法加载
       c = findClass(name);
   }
}
if (resolve) {
   resolveClass(c);
}
return c;
    }


查api发现ClassLoader有个方法返回Class<?> defineClass(String name,byte[] b, int off,int len),注意字节数组是由组成类数据的字节组成,所以我们可以以下列方式实现自己的类加载器(摘自深入理解java虚拟机)
public class MyCLassLoader {


    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        ClassLoader myCL = new ClassLoader() {


            @Override
            public Class<?> loadClass(String pathName) throws ClassNotFoundException {
               
               String fileName = pathName.substring(pathName.lastIndexOf(".") + 1) + ".class";
                byte b[] = null;
                try {
                    InputStream is = this.getClass().getResourceAsStream(fileName);
                    if(is == null){
                        return super.loadClass(pathName);
                    }
                    b = new byte[is.available()];
                    is.read(b);


                } catch (IOException ex) {
                    ex.printStackTrace();
                }


                return this.defineClass(pathName, b, 0, b.length);


            }
        };


 
        Class c = myCL.loadClass("arthur.java.fromInternet.MyCLassLoader");
        System.out.println(c);
        Object mcl = c.newInstance();
 
        System.out.println(mcl);
    }
}
原创粉丝点击