zoukankan      html  css  js  c++  java
  • JAVA-类加载机制(3)-类加载器

    类加载器

    作用:通过类全限定名来获取二进制字节流

    用例:类层次划分,OSGi,热部署,代码加密

    1,类和类加载器

      任意一个类和加载该类的加载器一同确立在虚拟机中的唯一性;

      每个类拥有独立的类名称空间;

      判断两个类是否相等,必须建立在同一个类加载器加载的前提下;否则会影响:equals, isAssignableFrom, isInstance, instanceof结果

    package com.classload.temp;
    
    import java.io.IOException;
    import java.io.InputStream;
    
    public class MainTest {
        
        public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
            
            ClassLoader myLoader = new ClassLoader(){
                @Override
                public Class<?> loadClass(String name) throws ClassNotFoundException {
    
                    try {
                        String fileName = name.substring(name.lastIndexOf(".") + 1) + ".class";
                        InputStream is = getClass().getResourceAsStream(fileName);
                        if(is == null){
                            return super.loadClass(name);
                        }
                        
                        byte[] b = new byte[is.available()];
                        is.read(b);
                        return defineClass(name, b, 0, b.length);
                    } catch (IOException e) {
                        throw new ClassNotFoundException(name);
                    }
                }
            };
            
            Object obj = myLoader.loadClass("com.classload.temp.MainTest").newInstance();
            System.out.println(obj.getClass());
            System.out.println(obj instanceof com.classload.temp.MainTest);
            
            /**
             * 执行结果: 
             *    class com.classload.temp.MainTest
             *    false                                  //obj使用了myLoader自定义类加载器,MainTest使用了应用程序类加载器,加载器不用所以为false
             */
        }
    }

    2,双亲委派模型

    类加载器分类

    方式一:①,启动类加载器: C++实现,是虚拟机自身一部分

          ②,其他类加载器:JAVA实现,独立于虚拟机外部,全部继承自抽象类java.lang.ClassLoader

    方式二:①,启动类加载器:加载JAVA_HOME/lib目录,或被-Xbootclasspath指定路径下,并被虚拟机识别的类库加载到虚拟机内存中

                   启动加载器不能被用户直接引用

                   用户编写自定义类加载器,需要把加载请求委派给引导类加载器,自定义类加载器使用null代替即可

        ②,扩展类加载器:加载JAVA_HOME/lib/ext目录下,或被java.ext.dirs系统变量指定的路径下类库

                 扩展类加载器可以直接被用户使用

                 sun.misc.Launcher$ExtClassLoader实现

        ③,应用程序类加载器:加载用户类路径上所指定的类库

                   该类加载器是ClassLoader中getSystemClassLoader()方法的返回值,有名系统类加载器

                 该类加载器可以直接被用户使用

                 sun.misc.Launcher$AppClassLoader实现

              

    类加载器之间的关系使用了组合关系复用父类加载器代码,而不是继承;

    双亲委派模型工作过程:

      如果一个类加载器收到类加载器的请求,首先不会自己尝试加载,而是将该请求委派给父类加载器完成,每个层次的类加载器都是如此;

      因此所有类加载请求最终都传送到顶层的类加载器中,只有当父类加载器无法加载时(搜索范围内未找到该类),子加载器才会去加载。

    双亲委派模型优点:

      ①,java类随着它的类加载器一起具备了一种带有优先级的层次关系

        如:java.lang.Object存放于rt.jar中无论哪个类加载器加载该类,都会被委派到顶层启动类加载器进行加载,

            因此Object类在程序的各种类加载器中都是同一个类

        如:编写与rt.jar类库中同名的java类,可以正常编译但是永远无法被加载运行(因为双亲委派)  

      ②,双亲委派模型并不是强制性的约束模型    

    双亲委派原理:

      1,检查该类是否被加载过

      2,没有加载过:

            父类加载器非空:调用父类加载器的loadClass()方法,

            父类加载器为空:默认使用启动类加载器作为父类加载器

            父类加载器加载失败:调用自己的findClass()方法加载

    3,破坏双亲委派模型

  • 相关阅读:
    [Give a try | Multithreading]The Practical Guide to Multithreading
    [SOLID]The Principles of OOD
    Mixing Native and Managed Types in C++
    [转载]关于大型软件重构的一些想法
    Mixed mode programming is the absolute power of C++/CLI
    Sample: Mixing Unmanaged C++, C++/CLI, and C# code
    添加删除虚函数带来的问题及解决办法
    如何阅读code base的组内讨论的总结
    如何快速定位一个函数的返回点(c/c++ Only)
    DirextX Training笔记
  • 原文地址:https://www.cnblogs.com/wanhua-wu/p/6577178.html
Copyright © 2011-2022 走看看