7.2 类加载的时机

类从被加载到VM内存中开始,到卸载出内存为止,它的生命周期包括了:加载,验证,准备,解析,初始化,使用,卸载,共7个阶段。其中验证,准备,解析统称为连接。

其中解析的顺序不一定,某些情况可以在初始化阶段后开始,这是为了支持Java的运行时绑定。
何时加载VM自己把握,但对于初始化,严格规定4种情况:

  1. 遇到new,getstatic,putstatic或invokestatic这4条字节码命令时。
    具体场景:用new关键字实例化对象时,读取或设置一个类的静态字段时,调用类静态方法时。
  2. 使用java.lang.reflect包的方法对类进行发射调用时
  3. 初始化类,发现其父类方法还没有初始化,先触发父类初始化(接口在初始化时,只有真正用到父接口才初始化)
  4. VM启动时,用户需要指定一个要执行的主类,VM会先初始化这个主类。

7.3 类加载的过程

加载阶段,VM完成三件事:
- 通过一个类的全限定名获取定义此类的二进制字节流(不一定从Class文件获取,ZIP包,网络,动态代理生成)
- 将此字节流代表的静态存储结构转化为方法区的运行时数据结构。
- 在Java堆中生成一个代表这个类的java.lang.Class对象,作为方法区这些数据的访问入口。

7.3.2 验证

确保Class文件的字节流包含的信息符合当前VM的要求,不会危害VM自身的安全。
Class文件不一定要求用java源码编译而来。可以使用任何途径,包括用十六进制编辑器直接编写产生。

  • 文件格式验证:字节流是否符合Class文件格式的规范
  • 元数验证:对字节码信息进行语义分析(元数据的数据类型),类是否有父类,类的父类是否继承了不允许被继承的类
  • 字节码验证:最复杂的阶段。进行数据流和控制流的分析(类的方法体校验分析)。保证任意时刻操作数栈的数据类型与指令代码序列都能配合工作。
  • 符号引用验证:(确保解析动作能正常运行)符号引用中通过字符串描述的全限定名是否能找到对于的类。符号引用中的类,字段和方法的访问性是否可被当前类访问。

7.3.3 准备

正式为类变量(不包括实例变量)分配内存并设置类变量初始0值的阶段。这些内存都在方法区。
public static final int value=123;准备阶段赋值为123,而没有final则会设置为0

7.3.4 解析

是VM将常量池内的符号引用替换为直接引用的过程。
符号引用以一组符号描述所引用的目标,与VM实现的内存布局无关,引用的目标不一定加载到内存中。
直接引用可以是直接指向目标的指针,与VM实现的内存布局相关。引用的目标必定在内存中存在。
接口动作主要针对:类或接口,字段,类方法,接口方法四类符号引用进行。

7.3.5 初始化

类加载过程的最后一步。真正开始执行类中定义的Java程序代码,根据程序制定的主观计划初始化变量和其他资源。
初始化阶段是执行类构造器()方法的过程。
<clinit>()方法是由是编译器自动收集类中的,所有类变量的赋值动作和静态语句块中的语句合并产生的。
父类的<clinit>()方法先执行,意味着父类定义的静态语句块优先于子类的变量赋值操作。
接口中不能使用静态语句块,但仍有变量初始化的赋值操作,因此接口与类一样有<clinit>()方法。
只有当父接口中定义的变量被使用时,父接口才会初始化。
VM会保证一个类的<clinit>()方法在多线程环境中被正确地枷锁和同步。


7.4 类加载器

通过类的全限定名获取此类的二进制字节流,这个动作放到JavaVM外部去实现。实现这个动作的代码块叫”类加载器“。让应用程序自己选择如何获取所需要的类。在类层次划分,OSGI,热部署,代码加密等领域有重要作用。

7.4.1 类与类加载器

对任一个类,都需要由加载他的类加载器和这个类本身一同确立其在JavaVM中的唯一性。

7.4.2 双亲委派模型

JavaVM角度看:只有两种不同的类加载器:一是启动类加载器(Bootstrap ClassLoader),是VM自身一部分(C++实现),另一种是所有其他的类加载器,用Java实现,全部继承于java.lang.ClassLoader。

  • 启动类加载器:将存放在\lib中的类库加载到VM内存中(按照文件名识别),无法被Java程序直接引用。
  • 扩展类加载器:将存放在\lib\ext中的类库加载到VM内存中
  • 应用程序加载器:加载ClassPath所指定的类库。

    上图就算双亲委派模型,除了顶层的启动类加载器,其他类加载器都该有自己的父类加载器。这里的父子关系不同该继承实现,而是用组合关系来复用父加载器的代码。
    JDK1.2引入,但不强制。
    如果收到请求,先委派给父类加载器完成。因此所有的加载请求都传送到顶层的启动类加载器中。只有父加载器反馈自己无法完成这个请求,子加载器才会尝试自己加载。

好处是:例如java.lang.Object类,无论哪个加载器请求加载,最后都给顶层的加载,因此Object类在各种类加载器环境中都是同一个类。

7.4.3 破坏双亲委派模型

双亲委派模型很好地解决了各个类加载器的基础类的统一问题(越基础的类由越上层的加载器进行加载)。当基础类又要调用回用户的代码,该怎么办?有了线程上下文加载器,JNDI服务(对资源进行集中查找和管理)使用它去加载所需要的SPI(服务提供接口)代码,就是说父加载器请求子类加载器去完成类加载的动作。

OSGI(Open Services Gateway Initiative,基于Java的动态模型系统)是Java模块化标准,实现模块化热部署的关键是它自定义的类加载器机制的实现。每一个程序模块(bundle)都有一个自己的类加载器。当需要更换一个bundle时,就把bundle连同类加载器一起换掉以实现代码的热替换。

OSGI环境,类加载器不是双亲委派模型的树状结构,而是网站结构。

  1. 将以java.*开头的类,委派给父类加载器加载。
  2. 否则,将委派列表名单内的类,委派给父类加载器加载。
  3. 否则,将Import列表中的类,委派给Export这个类的bundle的类加载器加载。
  4. 否则,查找当前Bundle的ClassPath,使用自己的类加载器加载。
  5. 否则,查找类是否在自己的Fragment Bundle中,如果在,则委派给Fragment Bundle的类加载器加载。
  6. 否则,查找Dynamic Import列表的Bundle,委派给对应的Bundle的类加载器加载。
  7. 否则,类查找失败。


    我觉得这篇写得算是,重新恢复了翔实·——·

《深入理解Java虚拟机》第7章 虚拟机类加载机制相关推荐

  1. 深入理解Java类型信息(Class对象)与反射机制

    关联文章: 深入理解Java类型信息(Class对象)与反射机制 深入理解Java枚举类型(enum) 深入理解Java注解类型(@Annotation) 深入理解Java并发之synchronize ...

  2. 深入理解java虚拟机 第7章 虚拟机类加载机制

    目录 7.1 概述 7.2 类加载的时机 类加载生命周期 开始顺序 类初始化时机 主动引用 被动引用 接口加载与类加载过程的区别 7.3 类加载的过程 7.3.1 加载 7.3.2 验证 7.3.3 ...

  3. java虚拟机类加载机制_《深入理解java虚拟机》学习笔记一/类加载机制

    为何要读这本书? 近期看了左萧龙大哥的单例设计模式,后文讲解到了JVM对类实例化相关知识,感觉看着很无力,不懂,于是乎买本书研究下. 如何读? 个人水平一般,理解程度有限,书中说到每章关联不是很大,所 ...

  4. java虚拟机类加载机制浅谈_浅谈Java虚拟机(三)之类加载机制

    在<浅谈Java虚拟机>这篇文章中,我们提到了JVM从操作系统方面来说,可以将其看做是一个进程,分别有类加载器子系统,执行引擎子系统和垃圾收集子系统.这一篇文章就简单的来谈一下类加载器子系 ...

  5. Java 工程师必须掌握的 JVM 类加载机制!

    这篇文章不聊别的,专门来侃侃JVM的类加载机制 概念 类加载器把class文件中的二进制数据读入到内存中,存放在方法区,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据 ...

  6. java类验证和装载顺序_java类加载机制,你会了吗?

    什么是类加载机制呢? java虚拟机将编译后的class文件加载到内存中,进行校验.转换.解析和初始化,到最终的使用.这就是java类加载机制: 下面就开始今天的内容: 1.类加载的生命周期:加载(L ...

  7. java类验证和装载顺序_Java类加载机制实现流程及原理详解

    前言 我们知道,Java项目编译后会生成许许多多的class文件,class文件保存着类的描述信息.虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验.转化解析和初始化,最终形成可以被虚 ...

  8. java的反射和它的类加载机制

    2019独角兽企业重金招聘Python工程师标准>>> 1. java 的类装载系统: 在java虚拟机中有两种类装载器: 启动类装载器 和 自定义类装载器. 前者是jvm的一部分, ...

  9. 无招胜有招之Java进阶JVM(八)类加载机制

    6.1.ClassLoader的两个作用和一个任务 作用:1.将Class加载到JVM中2.审视每一个类应该由谁加载. 任务:将Class字节码重新解析成统一要求的对象格式 6.2上级委托接待机制又称 ...

  10. java web 加载类_Tomcat类加载机制

    Tomcat Server在启动的时候将构造一个ClassLoader树,以保证模块的类库是私有的 Tomcat Server的ClassLoader结构如下: 代码 Bootstrap | Syst ...

最新文章

  1. Linux内核实现原子性操作cmpxchg指令的理解
  2. 设计模式复习-代理模式
  3. Javascript添加收藏夹和设为首页兼容写法
  4. java bufferedimage颜色_java – BufferedImage意外地改变了颜色
  5. 2019年第十届蓝桥杯国赛B组试题E-路径计数-dfs(坑题)
  6. jar 退出run_Java终止线程的三种方式
  7. 如何知道linux的ssh秘钥是否匹配,SSH密钥验证
  8. java构成对象的三要素_20155237 《JAVA程序设计》实验二(JAVA面向对象程序设计)实验报告...
  9. Appcan、apicloud、HBuilder 不同之处解析
  10. AttributeError: module ‘tensorflow‘ has no attribute ‘ConfigProto‘
  11. 大平房到朝阳环路时间表_冰蓄冷系统设计计算10大要点
  12. Android实现多国语言适配:app名称随系统的语言而更换
  13. java推箱子图片素材下载_推箱子游戏素材 箱子图 背景图 人物图
  14. 以下选项属于python哲学内容的是_[南开大学]18秋学期(清考)《哲学与人生》在线作业...
  15. 郭逸淵:4月7日比特幣(BTC)以太坊(ETH)行情分析及布局思路
  16. 中文分词jieba python 学习
  17. Unity如何实现投影阴影效果
  18. [内附完整源码和文档] 基于Java的高校团委团员档案管理系统
  19. 26.【C语言】字符串转无符号整型unsignedint、字符串转有符号整型int、无符号整型unsignedint转字符串、有符号整型转字符串(5_task)
  20. 基于Flutter开发网站转换成APP源代码 网站生成APP源代码带控制端

热门文章

  1. android与ndk交互,NDK-JNI与Java的交互 hello-world
  2. 晶体管游戏 linux,Industrial Linux
  3. 如何java面试_短时间如何过java面试?
  4. php time豪秒_PHP精确到毫秒秒杀倒计时实例详解
  5. 步进电机可以连续运转吗?
  6. C++面试题-面向对象-多态性与虚函数
  7. php语法基础考试,我的php学习第二十六天——PHP基础语法
  8. 【自然语言处理】--视觉问答(Visual Question Answering,VQA)从初始到应用
  9. Jquery第二篇【选择器、DOM相关API、事件API】
  10. linux自学笔记--DNS服务器