zoukankan      html  css  js  c++  java
  • JVM 类加载器 (二)

    1、类加载器(ClassLoader)负责加载class文件,class文件在文件开头有特定的文件标识,并且ClassLoader只负责 class 文件的加载,至于class文件是否能够运行则由Execution Engine决定;

      

     

    2、类的加载过程

    加载class文件 ---> 连接(验证、准备、解析class文件)----> 初始化类的对象 ----> 使用类的对象 -----> 卸载。

    (1)加载class文件

      取类的二进制字节流,通过类的全量命名,将静态存储结构房到方法区中,Class(类的定义或结构,即类对象)放到堆中; 

    (2)初始化类对象

      执行类的构造器<clinit>,为类的静态变量赋予正确的初值;

      构造器包含:static变量、static块;根据代码中的顺序来决定先执行哪个;

      先执行构造器(static变量、static块),再执行构造方法;

    3、JDK中的类加载器:

      <1> 启动类加载器(BootStrap ClassLoader): C++编写的,虚拟机自带的加载器;加载$JAVA_HOME/jre/lib/rt.jar 

      <2> 扩展类加载器(Extension ClassLoader):java编写;加载$JAVA_HOME/jre/lib/ext/*.jar

      <3> 应用程序类加载器(App ClassLoader):java编写;也叫系统类加载器,加载当前应用的 $classpath 下所有类

         <4> 用户自定义加载器:Java.Lang.ClassLoader 的子类,用户可以定制类的加载方式;

       

    3、类加载器说明

     第一步:将 MyHello 类打包成 jar包,然后放入$JAVA_HOME/jre/lib/ext/ 目录下。  MyHello内容如下:

    public class MyHello
    {
        public static void main(String[] args)
        {
    
        }
    }

       第二步:编写如下代码

    public class Demo1
    {
        public static void main(String[] args) throws ClassNotFoundException {
            //启动类加载器(BootStrap ClassLoader)
            Object object = new Object();
            System.out.println("Object-classLoader: " + object.getClass().getClassLoader());
            //结果: Object-classLoader: null
    
            //扩展类加载器 (Extension ClassLoader)
            Class myHello = Class.forName("com.yufeng.jvm.hello.MyHello");
            System.out.println("MyHello-classLoader: " + myHello.getClassLoader());
            //结果:MyHello-classLoader: sun.misc.Launcher$ExtClassLoader@7ea987ac
    
            //应用类加载器 (App ClassLoader)
            Demo1 classLoaderDemo1 = new Demo1();
            System.out.println("Demo1-classLoader: " + classLoaderDemo1.getClass().getClassLoader());
            //①结果:Demo1-classLoader: sun.misc.Launcher$AppClassLoader@18b4aac2
    
            System.out.println("Demo1-classLoader-parent: " + classLoaderDemo1.getClass().getClassLoader().getParent());
            //②结果:Demo1-classLoader-parent: sun.misc.Launcher$ExtClassLoader@2503dbd3
            
            System.out.println("Demo1-classLoader-parent-parent: " + classLoaderDemo1.getClass().getClassLoader().getParent().getParent());
            //③结果:Demo1-classLoader-parent-parent: null
        }
    }

    从以上的①、②、③可以看出,启动类加载器是扩展类加载器的父类,扩展类加载器是应用加载器的父类。

    打印出的Object的类加载器为null,表示它是根加载器,即启动类加载器。

    4、类加载器的双亲委派机制

       某个特定的类加载器在接到加载类的请求时,首先将加载任务委托给父类加载器,依次递归,若父类加载器可以完成类加载任务,就成功返回;只有父类加载器无法完成此加载任务时,才自己去加载。 

      这样设计为了保证java的一种安全特性--------沙箱机制(防止恶意代码对java的破坏);

      例:若自己新建了一个String类(classpath路径下),则类加载器是应用程序类加载器;加载的时候程序类加载器委托父类加载器加载(即扩展类加载器),扩展类加载器去委托启动类加载器去加载,rt.jar中有String.class文件,则会加载这个Class,不会加载自己新建的那个String类。

  • 相关阅读:
    详解Net Core Web Api项目与在NginX下发布
    一个C#开发者重温Java的心路历程
    C#使用Consul集群进行服务注册与发现
    让我们一起揭开算法的神秘面纱
    C#调用RabbitMQ实现消息队列
    C#调用OpenCV开发简易版美图工具
    我们是如何做go语言系统测试覆盖率收集的?
    高效测试框架推荐之Ginkgo
    性能测试必知必会
    如何保障Go语言基础代码质量?
  • 原文地址:https://www.cnblogs.com/yufeng218/p/9148048.html
Copyright © 2011-2022 走看看