zoukankan      html  css  js  c++  java
  • 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 = 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 = 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异常。

  • 相关阅读:
    hibernate 4 需要导入的jar包
    中国象棋马走日(要求打印每一种走法) — 递归
    最长公共子串
    国际象棋马走日(骑士周游)
    八皇后
    约瑟夫问题
    hashtable的运用实例
    用较小的代价去除字符串中的空格
    C++ string数据类型的实现
    strcpy、strncpy与memcpy的区别与使用方法
  • 原文地址:https://www.cnblogs.com/lzeffort/p/7078389.html
Copyright © 2011-2022 走看看