从类被加载到虚拟机内存中开始,到卸御出内存为止,它的整个生命周期分为7个阶段,加载(Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)、初始化(Initialization)、使用(Using)、卸御(Unloading)。其中验证、准备、解析三个部分统称为连接。
7个阶段发生的顺序如下:

1. 加载

  1. 通过一个类的全限定名来获取定义此类的二进制字节流。
  2. 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。
  3. 在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口。

    注意:JVM中的ClassLoader类加载器加载Class发生在此阶段

2. 验证

2.1 文件格式的验证

  1. 主要验证字节流是否符合Class文件格式的规范,如果符合则把字节流加载到方法区中进行存储。
  2. 文件头、主次版本验证等等

2.2 元数据验证

主要对字节码描述的信息进行语义分析,保证其描述符合Java语言的要求。
1. 类是否有父类
2. 是否继承了不允许被继承的类(final修饰过的类)
3. 如果这个类不是抽象类,是否实现其父类或接口中所有要求实现的方法
4. 类中的字段、方法是否与父类产生矛盾(如:覆盖父类final类型的字段,或者不符合个则的方法)

2.3 字节码验证

最复杂的一个阶段。主要目的是通过数据量和控制流分析,确定程序语义是合法的,符合逻辑的。
保证被校验类的方法在运行时不会做出危害虚拟机安全的事件。

2.4 符号引用验证

符号引用中通过字符串描述的全限定名是否能找到对应的类。
在指定类中是否存在符合方法的字段描述符以及简单名称所描述的方法和字段。
符号引用中的类、字段、方法的访问性(private、protected、public、default)是否可被当前类访问。

3、准备

准备阶段正式为类变量分配内存并设置初始值阶段。
public static int value=123; 初始后为 value=0;
对于static final类型,在准备阶段会被赋予正确的值
public static final value=123;初始化为 value=123;

如果是boolean值默认赋值为:false
如果是对象引用默认赋值为:null

**注意:
只设置类中的静态变量(方法区中),不包括实例变量(堆内存中),实例变量是在对象实例化的时候初始化分配值的**

4、解析

解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程。
1. 符号引用:简单的理解就是字符串,比如引用一个类,java.util.ArrayList 这就是一个符号引用,字符串引用的对象不一定被加载。
2. 直接引用:指针或者地址偏移量。引用对象一定在内存(已经加载)。

5、初始化

  1. 执行类构造器
  2. 初始化静态变量、静态块中的数据等(一个类加载器只会初始化一次)
  3. 子类的调用前保证父类的被调用

    **注意:
    是线程安全的,执行的线程需要先获取锁才能进行初始化操作,保证只有一个线程能执行(利用此特性可以实现线程安全的懒汉单例模式)。**

什么是类装载器ClassLoader

  1. ClassLoader是一个抽象类
  2. ClassLoader的实例将读入Java字节码将类装载到JVM中
  3. ClassLoader可以定制,满足不同的字节码流获取方式
  4. ClassLoader负责类装载过程中的加载阶段。

JVM中的类加载器

  1. 启动类加载器(BootStrap ClassLoader):引导类装入器是用本地代码实现的类装入器,它负责将 jdk中jre/lib下面的核心类库或-Xbootclasspath选项指定的jar包加载到内存中。由于引导类加载器涉及到虚拟机本地实现细节,开发者无法直接获取到启动类加载器的引用,所以不允许直接通过引用进行操作。
  2. 扩展类加载器(Extension ClassLoader):扩展类加载器是由Sun的ExtClassLoader(sun.misc.Launcher$ExtClassLoader)实现的。它负责将jdk中jre/lib/ext或者由系统变量-Djava.ext.dir指定位置中的类库加载到内存中。开发者可以直接使用标准扩展类加载器。
  3. 系统类加载器(System ClassLoader):系统类加载器是由 Sun的 AppClassLoader(sun.misc.Launcher$AppClassLoader)实现的。它负责将系统类路径java -classpath或-Djava.class.path变量所指的目录下的类库加载到内存中。开发者可以直接使用系统类加载器。

双亲委派模型

下图中展示了类加载器直接的关系和双亲委派模型

从图中我们发现除启动类加载器外,每个加载器都有父的类加载器。
双亲委派机制:如果一个类加载器在接到加载类的请求时,它首先不会自己尝试去加载这个类,而是把这个请求任务委托给父类加载器去完成,依次递归,如果父类加载器可以完成类加载任务,就成功返回;只有父类加载器无法完成此加载任务时,才自己去加载。


从类的继承关系来看,ExtClassLoader和AppClassLoader都是继承URLClassLoader,都是ClassLoader的子类。而BootStrapClassLoader是有C写的,不再java的ClassLoader子类中。

**注意:
从图中可以看到类加载器间的父子关系不是以继承的方式实现的,而是以组合关系的方式来复用父加载器的代码。
如果一个类加载器收到了类加载的请求,它首先会把这个请求委派给父加载器去完成,每一个层次的类加载器都是如此。 **

双亲委派模型的好处

Java类随着加载它的类加载器一起具备了一种带有优先级的层次关系。比如,Java中的Object类,它存放在rt.jar之中,无论哪一个类加载器要加载这个类,最终都是委派给处于模型最顶端的启动类加载器进行加载,因此Object在各种类加载环境中都是同一个类。如果不采用双亲委派模型,那么由各个类加载器自己取加载的话,那么系统中会存在多种不同的Object类。

破坏双亲委派模型

案例一

双亲委派模型的问题:顶层ClassLoader,无法加载底层ClassLoader的类。
JDK的javax.xml.parsers包中定义了xml解析的类接口
Service Provider Interface SPI 位于rt.jar 即接口在启动ClassLoader中。而SPI的实现类,可能由第三方提供,AppClassLoader进行加载。
解决思路:可以在线程中放入底层的ClassLoader到Thread. setContextClassLoader()中,然后在顶层ClassLoader中使用Thread.getContextClassLoader()获得底层的ClassLoader进行加载第三方实现。

案例二

Tomcat中使用了自定ClassLoader,并且也破坏了双亲委托机制。
每个应用使用WebAppClassloader进行单独加载,他首先使用WebAppClassloader进行类加载,如果加载不了再委托父加载器去加载,这样可以保证每个应用中的类不冲突。每个tomcat中可以部署多个项目,每个项目中存在很多相同的class文件(很多相同的jar包),他们加载到jvm中可以做到互不干扰。

案例三:

利用破坏双亲委派来java的类热部署实现(每次修改类文件,不需要重启服务)。
因为一个Class只能被一个ClassLoader加载一次,否则会报java.lang.LinkageError。当我们想要实现代码热部署时,可以每次都new一个自定义的ClassLoader来加载新的Class文件。JSP的实现动态修改就是使用此特性实现。

Class加密实现思路

ClassLoader加载.class文件的方式不仅限于从jar包中读取,还可以从种地方读取,因为ClassLoader加载时需要的是byte[]数组.

ClassLoader加载Class文件方式:
1. 从本地系统中直接加载
2. 通过网络下载.class文件
3. 从zip,jar等归档文件中加载.class文件
4. 从专有数据库中提取.class文件
5. 将Java源文件动态编译为.class文件

加密实现思路:加载Class文件的方式灵活,我们可以自定义ClassLoader,把加密后的Class文件,在加载Class前先进行解密,然后在通过ClassLoader进行加载。

本人简书blog地址:http://www.jianshu.com/u/1f0067e24ff8    
点击这里快速进入简书

GIT地址:http://git.oschina.net/brucekankan/
点击这里快速进入GIT

JVM 类加载机制深入浅出相关推荐

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

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

  2. jvm类加载机制_面试:对于JVM类加载机制深度解析

    目录: 前文回顾 JVM在什么情况下会加载一个类? 从实用角度出发,来看看验证.准备和初始化的过程 核心阶段:初始化 类加载器和双亲委派机制 1.前文回顾 咱们今天先来回顾一下昨天讲到的JVM整体的一 ...

  3. 【Java虚拟机规范】JVM类加载机制

    [Java虚拟机规范]JVM类加载机制 理论知识 一个类型从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期将会经历加载(Loading).验证(Verification).准备(Prep ...

  4. jvm类加载机制_JVM 类加载机制

    学习导图 一.为什么要学习类加载机制? 今天想跟大家唠嗑唠嗑 Java 的类加载机制,这是 Java 的一个很重要的创新点,曾经也是 Java 流行的重要原因之一. Oracle 当初引入这个机制是为 ...

  5. JVM类加载机制(ClassLoader)源码解析

    http://blog.csdn.net/chenyi8888/article/details/7066569 其实JVM类加载机制,简单地说就是类管理,也就是我们生成的class文件. 三个步骤:装 ...

  6. JVM(2)——JVM类加载机制

    一.JVM类加载机制简介 虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的类加载机制. 在Java语言里面 ...

  7. jvm类加载机制和类加载器_在JVM之下–类加载器

    jvm类加载机制和类加载器 在许多开发人员中,类加载器是Java语言的底层,并且经常被忽略. 在ZeroTurnaround上 ,我们的开发人员必须生活,呼吸,饮食,喝酒,并且几乎与类加载器保持亲密关 ...

  8. JVM类加载机制详解

    本文来详细说下JVM类加载机制 文章目录 概述 类加载器是什么 类加载的过程 加载 连接 初始化 类的主动引用和被动引用 主动引用 被动引用 三种类加载器 双亲委托机制 核心思想 源码分析 类的动态加 ...

  9. 详解JVM类加载机制

    详解JVM类加载机制 笔者的笔记都记录在有道云里面,因为公司原因办公电脑无法使用有道云,正好借此机会整理下以前的笔记顺便当做巩固复习了,也因为记笔记的时候不会记录这些知识来源何地,所以如果发现原创后可 ...

最新文章

  1. 人生赢家的三个最基本标准
  2. react 点击两次_javascript – 为什么在React中需要两次绑定onClick?
  3. ReactNative-触摸事件
  4. jinfo:JVM运行时配置的命令行浏览
  5. python删除文件夹中的jpg_Python简单删除目录下文件以及文件夹的方法
  6. 算法(18)-leetcode-剑指offer2
  7. Quartus17打开RTL视图
  8. html5页面的手势,HTML5单页面手势滑屏切换如何实现
  9. Atitit 算法的理解 目录 1. 算法(Algorithm),是程序的灵魂 1 2. 2. 算法的图形化表示 2 3. 3. 算法在实际软件开发项目中的应用 3 4. 算法的特点: 4 4.1.
  10. CMU 15-213 Introduction to Computer Systems学习笔记(8) Machine-Level Programming-Advanced
  11. matlab画图入门教程
  12. web调用IC卡读卡器开发第七章--NFC标签NDEF数据
  13. ios 国外账户的创建
  14. 图灵奖得主David Patterson出席2022全球软件研发技术大会
  15. Web功能测试(邮箱,手机号,验证码,身份证号测试用例)
  16. 用自己的APP打开微信和支付宝付款码和扫一扫界面
  17. python情感分析中文_Python有趣|中文文本情感分析
  18. python文件查重并合并_用python对excel查重
  19. 在家用手机兼职稳定收入,三种实战方法
  20. 利用powershell安装360杀毒

热门文章

  1. 四十八、第二份国外的Python考试(下篇)
  2. 四十二、Linux网络管理,软件安装,进程管理总结
  3. 影评情感分类(基于IMDB数据集)
  4. matplotlib.pyplot 和opencv 的结合画图
  5. linux cat代码,linux cat命令(示例代码)
  6. 如何做深ViT模型?NUS、字节:引入Re-attention机制,实现强大性能
  7. EMNLP 2020 | 通过Contrast Set评估模型的局部决策边界
  8. java的继承_java中的继承(一)
  9. 将Sql数据库中的表导出到指定文件
  10. 【Linux环境下安装Maven与环境配置简易教程】