• 038.[转] JVM启动过程与类加载


    From: https://blog.csdn.net/luanlouis/article/details/40043991

    Step 1.根据JVM内存配置要求,为JVM申请特定大小的内存空间 ?

    使用java.exe 启动JVM

    JVM启动时按照其配置要求,申请一块内存,并根据JVM规范和实现将内存划分为几个区域。

    所有的类的定义信息都会被加载到方法区。

    https://blog.csdn.net/xiangzhihong8/article/details/65657914

    配置JVM装载环境

      JVM.dll文件的查找和装载

    虚拟机参数解析、处理、验证

    设置线程栈大小

    新建JVM实例

    Step 2. 创建一个引导类加载器实例,初步加载系统类到内存方法区区域中;

    JVM申请好内存空间后,JVM会创建一个引导类加载器(Bootstrap Classloader)实例,引导类加载器是使用C++语言实现的。
    引导类加载器(Bootstrap Classloader)会读取{JAVA_HOME}/jre/lib下的rt.jar(java核心类库)和配置(JVM虚拟机运行时所需的基本系统级别的类),然后将这些系统类加载到方法区内。

    rt.jar 如java.lang.String, java.lang.Object等等。 

    Step 3. 创建JVM 启动器实例 Launcher,并取得系统类加载器ClassLoader

    此时,JVM虚拟机调用已经加载在方法区的类sun.misc.Launcher 的静态方法 getLauncher(), 获取 sun.misc.Launcher 实例

    sun.misc.Launcher launcher = sun.misc.Launcher.getLauncher(); //获取Java启动器
    ClassLoader classLoader = launcher.getClassLoader();          //获取类加载器ClassLoader用来加载class到内存来;
    // 返回 AppClassLoader 实例,AppClassLoader将ExtClassLoader作为自己的父加载器。
    sun.misc.Launcher 使用了单例模式设计,保证一个JVM虚拟机内只有一个sun.misc.Launcher实例。
    在Launcher的内部,其定义了两个类加载器(ClassLoader),分别是sun.misc.Launcher.ExtClassLoader和sun.misc.Launcher.AppClassLoader,
    这两个类加载器分别被称为拓展类加载器(Extension ClassLoader) 和 应用类加载器(Application ClassLoader).

    拓展类加载器(Extension Class Loader):

      该加载器是用于加载 java 的拓展类 ,拓展类一般会放在 {JAVA_HOME}/jre/lib/ext/ 目录下,用来提供除了系统类之外的额外功能。

      拓展类加载器是是整个JVM加载器的Java代码可以访问到的类加载器的最顶端,即是超级父加载器,拓展类加载器是没有父类加载器的?(即bootstrap classLoader?)。

    应用类加载器/系统类加载器(Applocatoin Class Loader):

      该类加载器是用于加载用户代码,是用户代码的入口。我经常执行指令 java   xxx.x.xxx.x.x.XClass , 实际上,JVM就是使用的AppClassLoader加载 xxx.x.xxx.x.x.XClass 类的。

      双亲委托模型:应用类加载器将拓展类加载器当成自己的父类加载器,当其尝试加载类的时候,首先尝试让其父加载器-拓展类加载器加载;如果拓展类加载器加载成功,则直接返回加载结果Class<T> instance,加载失败,则会询问是否引导类加载器已经加载了该类;只有没有加载的时候,应用类加载器才会尝试自己加载。

    Step 4. 使用类加载器ClassLoader加载Main类

    通过 launcher.getClassLoader()方法返回AppClassLoader实例,接着就是AppClassLoader加载我们写的 xxx.xxx.TestMain类的时候了。

    当AppClassLoader要加载 xxx.xxx.TestMain.class时,会去查看该类的定义,class文件中有一个叫常量池(Constant Pool)的结构体来存储该class的常量信息。常量池中有CONSTANT_CLASS_INFO类型的常量,表示该class中声明了要用到那些类。.xxx.xxx.TestMain类要想正常工作,首先要能够保证这些其内部声明的类加载成功。所以AppClassLoader要先将这些类加载到内存中。

    JVM方法区的类信息区是按照类加载器进行划分的,每个类加载器会维护自己加载类信息;
    某个类加载器在加载相应的类时,会相应地在JVM内存堆(Heap)中创建一个对应的Class<T>,用来表示访问该类信息的入口

     

    Step 5. 使用Main类的main方法作为程序入口运行程序

    Step 6. 方法执行完毕,JVM销毁,释放内存

  • 相关阅读:
    Java实现 蓝桥杯 历届试题 连号区间数
    Java实现 蓝桥杯 历届试题 连号区间数
    Java实现 蓝桥杯 历届试题 连号区间数
    Java实现 蓝桥杯 历届试题 连号区间数
    Java实现 蓝桥杯 历届试题 连号区间数
    Java实现 蓝桥杯 历届试题 大臣的旅费
    Java实现 蓝桥杯 历届试题 大臣的旅费
    Java实现 蓝桥杯 历届试题 大臣的旅费
    Java实现 蓝桥杯 历届试题 大臣的旅费
    Navicat查询哪些表有指定字段名
  • 原文地址:https://www.cnblogs.com/badboyh2o/p/11267068.html
Copyright © 2020-2023  润新知