Java虚拟机-类加载器

1.类加载器

  • 虚拟机的设计团队把类加载阶段中的“通过一个类的全限定名来获取描述此类的二进制流”这个动作放到Java虚拟机外部去实现,以便让应用程序自己决定如何去获取所需要的类。实现这个动作的代码模块称之为类加载器。
  • 只有被同一个类加载器加载的类才可能会相等。相同的字节码被不同的类加载器加载的类不相等。

2.类加载器分类

  •     启动类加载器

           由C++实现,是虚拟机的一部分,用于加载javahome下的lib目录下的类。

  •     扩展类加载器

           加载javahome下/lib/ext目录中的类。

  •     应用程序类加载器

           加载用户类路径上所指定的类库。 

  •     自定义类加载器

3.自定义类加载器

  •     步骤

        定义一个类,继承ClassLoader。
        重写loadClass方法。
        实例化Class对象。

  •     优势

        类加载器是Java语言的一项创新,也是Java语言流行的重要原因之一,它最新的设计是为了满足Java Applet的需求而开发出来的。
        高度的灵活性。
        通过自定义类加载器可以实现热部署。
        代码加密。

  • 示例代码

public class ClassLoaderDemo {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        MyClassLoader myClassLoader = new MyClassLoader();
        Object c = myClassLoader.loadClass("com.my.classloader.ClassLoaderDemo").newInstance();

        System.out.println(c.getClass());
        // c由自定义类加载器加载,而ClassLoaderDemo由应用程序类加载器加载
        // 是两个不同的类加载器,一个类由两个不同的了加载器加载,所以两个类不相等
        System.out.println(c instanceof ClassLoaderDemo);
    }
}

class MyClassLoader extends ClassLoader {
    @Override
    public Class<?> loadClass(String name) throws ClassNotFoundException {
        String fileName = name.substring(name.lastIndexOf(".") + 1) + ".class";
        InputStream inputStream = getClass().getResourceAsStream(fileName);
        if (inputStream == null) {
            return super.loadClass(name);
        }
        try {
            byte[] buffer = new byte[inputStream.available()];
            inputStream.read(buffer);
            return defineClass(name, buffer, 0, buffer.length);
        } catch (Exception e) {
            throw new ClassNotFoundException();
        }
    }
}

4.双亲委派模型
          从JDK1.2开始,java虚拟机规范推荐开发者使用双亲委派模型进行类加载,其加载过程如下:

                                                       
          如果一个类加载器收到了类加载请求,它首先不会自己尝试加载这个类,而是把类加载请求委派给父类加载器去完成。每一层的类加载器都把类加载请求委派给父类加载器,直到所有的类加载请求都应该传递给顶层的启动类加载器。如果顶层的启动类加载器无法完成加载请求,子类加载器尝试去加载,如果连最初发类加载请求的类加载器也无法完成加载请求时,将会抛出ClassNotFoundException,而不再调用其子类加载器去进行类加载。双亲委派模型的类加载机制的优点是java类和它的类加载器一器具备了一种带优先级的层次关系,越是基础的类,越是被上层的类加载器进行加载,保证了java程序的稳定运行。

猜你喜欢

转载自blog.csdn.net/qq_22866497/article/details/81074869