zoukankan      html  css  js  c++  java
  • JVM -- 类加载相关

    0、前言

    以下都是基于 HotSpot 虚拟机

     

    1、JVM 的整体结构

    概览图:

            

     

     

    详细图:

     

     

    运行时数据区详细解释:

    JDK8 之后把方法区划成了元数据区域,其实元数据+JIT编译产物都可以称作非堆区

     

     

     

    2、类的加载过程

    类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括:加载、验证、准备、解析、初始化、使用和卸载七个阶段。它们的顺序如下图所示:

    具体每一步都干了什么 => 参考链接

    其中注意

    1)链接(link)中的 准备(prepare)阶段会给类变量(用static修饰的)赋默认值,比如 int 的默认值是 0

    2)加载(load)只负责将类的二进制信息加载进来,不负责其他。

    3)类的初始化时机有触发条件,如下主动使用的情况

     结合 2)和 3)于是就有了Class.forName 和 ClassLoader.load 的区别,参考此链接

     3、类加载过程的类加载器

     

     1) Bootstrap Class Loader

    2) Extension Class Loader

     3) Application Class Loader

     

     BTW:

    JVM中如何判断两个Class对象是否是同一个类需要满足两个条件

    1)类的完整类名必须完全一致,包括包名

    2)加载类的类加载器必须也是相同的!

    也就是说,即便是同一个 Class 文件出来的类信息,只要使用的加载器不一样,那在 JVM 中就不能视为同一个类

    4、关于 ClassLoader 类

     

    注:点开 sun.misc.Launcher 源码可以看到 ExtClassLoader 和 AppClassLoader 是其内部类,而 Launcher 是由 BootstrapClassLoader 加载。详情可以参考此链接

    在代码中可以有三种方式来获取 ClassLoader 类。详情参考此链接

     

     5、双亲委派机制

     

    好处 :这个机制保护了基础类不被蓄意 "破坏",例如类java.lang.Object,它存在在rt.jar,无论哪一个类加载器要加载这个类,最终都是委派给处于模型最顶端的Bootstrap ClassLoader进行加载,因此Object类在程序的各种类加载器环境中都是同一个类。相反,如果没有双亲委派模型而是由各个类加载器自行加载的话,如果用户编写了一个java.lang.Object的同名类并放在ClassPath中,那系统中将会出现多个不同的Object类,程序将混乱。因此,如果开发者尝试编写一个与rt.jar类库中重名的Java类可以正常编译,但是永远无法被加载运行。

    特殊情况:有时候父加载器需要子加载器对某些类进行加载,需要破坏原本的 "向上" 传递的规则 ,于是就有了 Thread.currentThread().getContextClassLoader() 具体参考此链接

  • 相关阅读:
    Go Example--json
    Go-struct
    Flutter高级进阶------Flutter Package、Flutter Plugin、Flutter Module
    Flutter项目实操---资讯、发布动弹
    Kotlin项目实战之手机影音---首页mvp重构、网络框架封装、重构首页数据加载、home页面view解绑
    vscode多处编辑
    配制vscode环境
    vscode配制perl环境
    R基本函数总结
    Git使用方法
  • 原文地址:https://www.cnblogs.com/qwertiLH/p/12505440.html
Copyright © 2011-2022 走看看