zoukankan      html  css  js  c++  java
  • 深入java虚拟机学习 -- 类的加载机制(四)

    类加载的命名空间

    每个类加载器都有自己的命名空间,命名空间由所有以此加载器为初始类加载器的类组成,不同命名空间的两个类是不可见的,但只要得到类所对应的Class对象的refrence(反射),还是可以访问另一个命名空间的类信息的。

    同一个命名空间内的类是相互可见的,子加载器的命名空间包含所有父加载器的命名空间,也就是说由子加载器加载的类能看到父加载器加载的类。例如:系统类加载器加载的类能看到根类加载器加载的类(用户自定的类可以访问java.lang.*包下的信息),由父加载器加载的类不能看到子加载器加载的类。

    如果两个加载器之间没有直接或者间接的父子关系,那么它们个字加载的类相互不可见。

    创建用户自定义的类加载器

    要创建用户自定义的类加载器,只需要扩展java.lang.ClassLoader类,然后覆盖它的findClass(String name)方法即可,该方法根据参数指定的类的名字,返回对应的Class对象的引用。

    protected Class<?> findClass(String name) throws ClassNotFoundException {
            throw new ClassNotFoundException(name);
        }

    我们可以按到ClassLoader里面的findClass方法的默认实现会抛出ClassNotFoundException异常,我们只需要在自定义的加载器里面重写,即可。

    public class MyClassLoader extends ClassLoader
    {
    
        private String name;//类加载器的名字
        private String path="";//加载类的默认路径
        private String fileType=".class"; //class文件的扩展名
    
        public MyClassLoader(String name){
            super();//让系统类加载器成为该类加载器的父加载器
            this.name=name;
        }
        public MyClassLoader(ClassLoader parent,String name){
            super(parent);//显示指定该类加载器的父加载器
            this.name=name;
        }
    
        @Override public String toString()
        {
            return this.name;
        }
    
        public String getPath()
        {
            return path;
        }
    
        public void setPath(String path)
        {
            this.path = path;
        }
    
        /**
         * 抽象类ClassLoader的findClass函数默认是抛出异常的。而前面我们知道,
         * loadClass在父加载器无法加载类的时候,就会调用我们自定义的类加载器中的findeClass函数,
         * 因此我们必须要在loadClass这个函数里面实现将一个指定类名称转换为Class对象.
         * @param name
         * @return
         */
        @Override protected Class<?> findClass(String name)
        {
            byte [] data=this.loadClassData(name);
            return this.defineClass(name,data,0,data.length);
        }
    
        private byte[] loadClassData(String name)
        {
            InputStream is=null;
            byte [] data=null;
            ByteArrayOutputStream baos=null;
            try
            {
                this.name=this.name.replace(".","\");
                is=new FileInputStream(new File(path+name+fileType));
                baos=new ByteArrayOutputStream();
                int ch=0;
                while(-1!=(ch=is.read())){
                    baos.write(ch);
                }
                data= baos.toByteArray();
            }
            catch(Exception e){
             e.printStackTrace();
            }
            finally
            {
                try
                {
                    is.close();
                    baos.close();
                }
                catch(IOException e)
                {
                    e.printStackTrace();
                }
            }
            return data;
        }
    
        public static void main(String[] args) throws Exception
        {
            MyClassLoader loader1 = new MyClassLoader("loader1");//没有指定loader的父加载器,则默认的父加载器为系统类加载器
            loader1.setPath("G:\myapp\loader1\");
    
            MyClassLoader loader2 = new MyClassLoader(loader1,"loader2");//指定loader2的父加载器为loader1,这里的loader1和loader2都为MyClassLoader的实例
            loader2.setPath("G:\myapp\loader2\");
    
            MyClassLoader loader3 = new MyClassLoader(null,"loader3");//bootstrap类加载器
            loader3.setPath("G:\myapp\loader3\");
    
            //test(loader1);
            test(loader2);
            test(loader3);
        }
    
        public static void test(ClassLoader loader) throws Exception
        {
            Class clazz=loader.loadClass("Sample");
            Object object=clazz.newInstance();
        }
  • 相关阅读:
    sql中生成随机字符串的function
    postgresql中uuid的使用
    sql中循环的存储过程
    java发送http的get、post请求
    data:image/png;base64
    Matcher和Pattern总结
    OPENXML解析sp_xml_preparedocument获取的XML句柄
    SqlServer性能优化
    python的2D绘图库matplotlib
    sift&surf检测关键点及描述子
  • 原文地址:https://www.cnblogs.com/blueskyli/p/8588662.html
Copyright © 2011-2022 走看看