首页 > 代码库 > Tomcat学习笔记(七)

Tomcat学习笔记(七)

 

  Tomcat载入器(一)

       在了解tomcat的载入器时,首先需要了解的是java的类加载部分的内容。

         在java体系中,系统分为3中类型的加载器

         1.启动类加载器(Bootstrap ClassLoader):加载对象为java核心库,采用c/c++实现,并不继承java.lang.ClassLoader,负责加载java_home/jre/lib目录下的类库,同时也属于JVM的一部分,在JVM启动时,将被加载到内存中。启动类加载器不能被java程序直接使用。

         2.扩张类加载器(Extension ClassLoader): 加载对象为java扩张库,即java_home/jre/lib/ext目录下面的类,这个类由启动类加载器加载,它的父类加载器为启动类加载器。

         3.应用程序类加载器(Application ClassLoader):也成为系统类加载器(System ClassLoader)它负责加载用户路径(classpath)指定的类库,它也是有启动类加载器加载,它的父类加载被设置为启动类加载器,可以通过ClassLoader.getSystemClassLoader()获取。

                                                                  技术分享

          tip:启动类加载器是扩展类加载器的父类加载器,并不是继承关系。

          越重要的类加载器就越早被载入JVM,这是考虑到安全性,因为先加载的类加载会充当下一个类加载器的父类加载器,在双亲委托模型机制下,就能确保安全性。双亲委托模型会在类加载加载类时,首先委托父类加载器进行加载,如果父类加载器不能加载,才自己加载。这种机制有效的保证java的安全。

        类加载的流程图。

                                                                       技术分享

下面用2个例子实现自定义的类加载器。

    1.采用JVM的双亲委托机制实现。

     测试类: Test.java

    

package com.test.load;
public class Test {   
    public Test(){
        System.out.println(this.getClass().getClassLoader().toString());
    }
}

   MyClassLoader.java

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

public class MyClassLoader extends ClassLoader
{

    private String name;
    
    public MyClassLoader(ClassLoader parent, String name)
    {
        super(parent);
        this.name = name;
    }
    @Override
    public String toString()
    {
        return "test:::"+this.name;
    }
    
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException
    {
        InputStream is = null;
        byte[] data = http://www.mamicode.com/null;
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try
        {
            is = new FileInputStream(new File("F:/work/web/Test.class"));
            int c = 0;
            while(-1 != (c = is.read())){
                baos.write(c);
            }
            data = baos.toByteArray();
        } catch (Exception e)
        {
            e.printStackTrace();
        }finally{
            try
            {
                is.close();
                baos.close();
            } catch (IOException e)
            {
                e.printStackTrace();
            }
        }
        return this.defineClass(name, data, 0, data.length);
    }
    public static void main(String[] args)
    {
        MyClassLoader loader = new MyClassLoader(MyClassLoader.class.getClassLoader(), "MyClassLoader");
        Class clazz;
        try
        {
            clazz = loader.loadClass("com.test.load.Test");
            Object object = clazz.newInstance();
        } catch (Exception e)
        {
            e.printStackTrace();
        }
    }
}

2.采用打破委托机制。

public class MyClassLoader2 extends ClassLoader
{

    private String name;
    
    public MyClassLoader2(ClassLoader parent, String name)
    {
        super(parent);
        this.name = name;
    }
    @Override
    public String toString()
    {
        return "test2:::"+this.name;
    }
    @Override
    public Class<?> loadClass(String name) throws ClassNotFoundException
    {
        Class<?> clazz = null;
        ClassLoader systemLoader = getSystemClassLoader();
        try
        {
            //打破委托机制
            clazz = systemLoader.loadClass(name);
        } catch (Exception e)
        {
            //忽略错误
            //e.printStackTrace();
        }
        if(clazz != null)
            return clazz;
        //自己加载
        clazz = findClass(name);
        return clazz;
    }
    @Override
    public Class<?> findClass(String name) throws ClassNotFoundException
    {
        InputStream is = null;
        byte[] data = http://www.mamicode.com/null;
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try
        {
            is = new FileInputStream(new File("F:/work/web/Test.class"));
            int c = 0;
            while(-1 != (c = is.read())){
                baos.write(c);
            }
            data = baos.toByteArray();
        } catch (Exception e)
        {
            e.printStackTrace();
        }finally{
            try
            {
                is.close();
                baos.close();
            } catch (IOException e)
            {
                e.printStackTrace();
            }
        }
        return this.defineClass(name, data, 0, data.length);
    }
    public static void main(String[] args)
    {
        MyClassLoader2 loader = new MyClassLoader2(MyClassLoader2.class.getClassLoader(), "MyClassLoader2");
        Class clazz;
        try
        {
            clazz = loader.loadClass("com.test.load.Test");
            Object object = clazz.newInstance();
        } catch (Exception e)
        {
            e.printStackTrace();
        }
    }
}

还可以测试一下类加载的流程是否正确,先将Test.class文件移走,看程序是出现ClassNotFoundException异常。

 

Tomcat学习笔记(七)