这篇文章我们关注一个问题:Java程序是怎么进入JVM并执行的?经常写Java程序的小伙伴应该都听说过类加载机制,在《深入理解Java虚拟机》里周老师已经讲的很清楚了,这篇随笔把之前的笔记以及一些总结重新梳理一下。前面我们已经知道 .java文件经过编译后变成Class文件,JVM加载的是字节码文件。这其中的细节不知道小伙伴们有么有了解过?

   类从被JVM加载到内存开始,到卸载出内存为止,整个生命周期包括7个阶段,加载、验证、准备、初始化、卸载这个5个步骤顺序是确定的。

  • 加载,类的加载时机由JVM自行决定,JVM需要完成3件事情:

    • 通过类的全限定名获取类的二进制字节流
    • 将类的静态存储结构转化为方法区的运行时数据结构
    • 在内存中生成类的Class对象,作为方法区数据的入口

  数组在Java中是一种引用类型,数组类的加载由Java虚拟机直接创建。类加载完成后,二进制字节流存储在方法区中,HotSpot虚拟机会创建一个java.lang.Class对象作为程序访问方法区中的数据的外部接口,这个Class对象存储在方法区中,加载阶段何连接部分阶段是交叉进行的。

  • 验证是连接部分的第一步,验证阶段是确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。因为只有在字节码层面才能保证Java语言的相对安全性。验证阶段会大致完成4个阶段的检验动作:

    • 文件格式验证:验证字节流是否符合Class文件格式的规范,并且能被当前版本的JVM处理。只有验证通过了,字节流才会进入方法区存储。
    • 元数据验证:比如类是否有父类,类是否继承了不能被继承的类等,保证不存在不符合Java语言规范的元数据信息。
    • 字节码验证:对类的方法体进行校验分析
    • 符号引用验证:对常量池中的各种符号引用进行校验
  • 准备:为类变量分匹内存并设置类型变量的零值阶段。类变量指的是被static修饰的变量,不包括实例变量。例如变量i,在准备阶段值就是0L,只有在执行方法的时候值才会变成1。
private static long a = 1;
  • 解析:JVM将常量池内的符号引用替换为直接引用的过程。这里要解释下符号引用何直接引用。

    • 符号引用: 用一组符号描述所引用的目标,引用的目标不一定已经加载到内存中。
    • 直接引用:直接指向目标的指针、相对偏移量、间接定位到目标的句柄,直接引用的目标已经在内存中。
  • 初始化,类加载过程的最后一步,执行类构造器<clinit>()方也就是真正执行类中定义的Java程序代码。遇到使用new关键字实例化对象、读取或设置一个类的静态字段、调用一个类的静态方法这些场景时,如果类没有被初始化,使用java.lang.reflect包的方法对类进行 反射调用时,那么一定要先初始化。还有一种场景是初始化子类时,如果父类没有被初始化,那么要先初始化父类。再看下接口的初始化,与类不同的地方就在于父类的初始化,子接口在使用到父接口的时候才初始化。在多线程环境中,如果多个线程同时初始化一个类,那么只有线程执行类的<clinit>()方法。

  JVM加载字节码文件靠的是类加载器,这个操作是在JVM外部实现的。这样应用程序就可以自己决定如何获取所需的类。如果两个类来自同一个Class文件,但是由不同的类加载器加载,那么者两个类一定是不相等。从JVM角度讲,只有两种加载器。一种是启动类加载器,是虚拟机自身的一部分,由C++语言实现;还有就是其他类加载器,由Java语言实现,全都继承自抽象类java.lang.ClassLoader 独立于虚拟机外部。

  从开发角度看,主要分为这三种:

  • 启动类加载器(Bootstrap ClassLoader):加载<JAVA_HOME>\lib目录中,或者被 -Xbootclasspath参数所指定的路径中。
  • 扩展类加载器(Extension ClassLoader):主要加载<JAVA_HOME>\lib\ext目录中的
  • 应用程序类加载器(Application ClassLoader):加载用户类路径(ClassPath)上所指定的类库。如果我们没有自定义过自己的类加载器,那么这就是程序默认的类加载器。

  这些类加载器之间的关系为:

  在使用类加载器加载类的过程种,最好遵循双亲委派模型。双亲委派的原理是:类加载器收到加载类的请求时,先把这个请求委派给父类加载去完成,每一层次的加载器按这个这个逻辑执行。那么所有的加载请求最终都应该传送到顶层的启动类加载中。父加载器无法加载,子加载器才会自己加载。这样做的好处是可以避免类的重复加载,保证程序运行的稳定性。

  我们可以自定义类加载器,总结起来就是:(1)类继承ClassLoader (2) 重写findClass() 方法 (3) 调用defineClass()方法。在loadClass()里如果父类加载失败,调用findClass()方法加载。破会双亲委派需要重写loadClass()方法。

  参考资料:《深入理解Java虚拟机》第二版 周志明

       《深入拆解Java虚拟机》郑雨迪

JVM类加载机制小结的更多相关文章

  1. JVM基础系列第7讲:JVM 类加载机制

    当 Java 虚拟机将 Java 源码编译为字节码之后,虚拟机便可以将字节码读取进内存,从而进行解析.运行等整个过程,这个过程我们叫:Java 虚拟机的类加载机制.JVM 虚拟机执行 class 字节 ...

  2. JVM总结(四):JVM类加载机制

    这一节我们来总结一下JVM类加载机制.具体目录如下: 类加载的过程 类加载过程概括 说说引用 详解类加载全过程: 加载 验证 准备 解析 初始化 虚拟机把描述类的数据从Class文件加载到内存,并对数 ...

  3. JVM 类加载机制详解

    如下图所示,JVM类加载机制分为五个部分:加载,验证,准备,解析,初始化,下面我们就分别来看一下这五个过程. 加载 加载是类加载过程中的一个阶段,这个阶段会在内存中生成一个代表这个类的java.lan ...

  4. Java虚拟机(四):JVM类加载机制

    1.什么是类的加载 类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构 ...

  5. JVM类加载机制详解(二)类加载器与双亲委派模型

    在上一篇JVM类加载机制详解(一)JVM类加载过程中说到,类加载机制的第一个阶段加载做的工作有: 1.通过一个类的全限定名(包名与类名)来获取定义此类的二进制字节流(Class文件).而获取的方式,可 ...

  6. JVM类加载机制(转)

    原文出自:http://www.cnblogs.com/ityouknow/p/5603287.html 1.什么是类的加载 类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运 ...

  7. JVM类加载机制详解

    引言 如下图所示,JVM类加载机制分为五个部分:加载,验证,准备,解析,初始化,下面我们就分别来看一下这五个过程. 加载 在加载阶段,虚拟机需要完成以下三件事情: 1)通过一个类的全限定名来获取定义此 ...

  8. Android动态加载--JVM 类加载机制

    动态加载,本质上是通过JVM类加载机制将插件模块加载到宿主apk中,并通过android的相关运行机制,实现插件apk的运行.因此熟悉JVM类加载的机制非常重要. 类加载机制:虚拟机把描述类的数据从C ...

  9. Java虚拟机(五):JVM 类加载机制

    一.JVM 类加载机制 JVM 类加载机制分为五个部分:加载,验证,准备,解析,初始化,下面我们就分别来看一下这五个过程. 1. 加载: 加载是类加载过程中的第一个阶段,这个阶段会在内存中生成一个代表 ...

随机推荐

  1. Java实现 蓝桥杯 基因牛的繁殖

    基因牛的繁殖 张教授采用基因干预技术成功培养出一头母牛,三年后,这头母牛每年会生出1头母牛, 生出来的母牛三年后,又可以每年生出一头母牛.如此循环下去,请问张教授n年后有多少头母牛? 以下程序模拟了这 ...

  2. java实现输入信用卡号码

    /* 当你输入信用卡号码的时候,有没有担心输错了而造成损失呢?其实可以不必这么担心, 因为并不是一个随便的信用卡号码都是合法的,它必须通过 Luhn 算法来验证通过. 该校验的过程: 1.从卡号最后一 ...

  3. mysql基础之-mysql存储引擎概述(八)

    0x01 mysql 存储引擎:存储引擎也通常被称作“表类型” mysql> show engines;   --- 查看当前所有所支持的存储引擎 mysql> show table st ...

  4. 温故知新-快速理解zookeeper功能&应用&选举机制

    文章目录 zookeeper简介 什么是zookeeper zookeeper应用场景 zookeeper特点 zookeeper的角色 zookeeper的数据模型 节点数据结构 节点类型 zook ...

  5. HDU-4341 Gold miner 题解

    题目大意 黄金矿工的游戏,不过每个金块可以看做是质点,没有大小,给出每个金块的坐标.抓取所花费的时间(包括返回的时间),以及价值,其中有一些金块可能会共线.求在规定时间内所获得的最大价值. 样例 样例 ...

  6. 使用PD(Power Designer)设计数据库,并且生成可执行的SQL文件创建数据库(本文以SQL Server Management Studio软件执行为例)

    下载和安装PD: 分享我的软件资源,里面包含了对PD汉化包(链接出问题时可以留言,汉化包只能对软件里面部分菜单栏汉化) 链接:https://pan.baidu.com/s/1lNt1UGZhtDV8 ...

  7. 前端JS的服务订阅&服务发布

    var eventCenter = { sub:function(mesName, mesCallback){ this.argus=this.argus||{}; this.argus[mesNam ...

  8. Ement 学习

    <!DOCTYPE html><html lang="en"><head> <meta http-equiv="Content- ...

  9. 05.Java面向对象

    一.面向对象基本概念 面向对象的特征 封装 封装是指利用抽象数据类型将数据(属性)和对数据的操作(方法)包装起来,把对象的属性和动作结合成一个独立的单位,并尽可能隐蔽对象的内部处理细节. 继承 一个类 ...

  10. [noi.ac省选模拟赛20200606]赌怪

    题目   点这里看题目. 分析   先特判掉\(K=2\)的情况.   首先可以考虑到一个简单 DP :   \(f(i)\):前\(i\)张牌的最大贡献.   转移可以\(O(n^2)\)地枚举区间 ...