JVM的类加载
一、基本类加载机制介绍
大体引用一下《深入理解Java虚拟机》一书中对类加载的定义:虚拟机将描述类的二进制字节流(即Class文件)加载到内存中,并对其进行验证、准备、解析、初始化,最终
生成可以直接被虚拟机使用的Java类型(即已经校验合格且有clinit执行完clinit方法的Class对象),这就是JVM的类加载机制。
一个好的定义,就应该是这样准确而简练的。下面先罗列一下类的生命周期:
加载 -> 验证 -> 准备 -> 解析 -> 初始化 -> 使用 -> 卸载
其中加载、验证、准备、初始化、卸载一定会严格按照上面的顺序进行。既然知道了类加载的大体流程,那么问题来了,什么时候会触发类的加载呢?
虚拟机规范中并未作出明确的要求,但是会要求有且仅有下面五种情况发生的时候,会触发类的初始化(言外之意就是初始化之前的动作必须在此之前完成),这五种情况分别为:
1、遇到new、getStatic、putStatic、invokeStatic字节码指令时;
2、通过java.lang.reflect包对类进行反射调用的时候;
3、初始化子类时,如果父类没初始化,则先初始化父类(接口除外,接口初始化规则是调用哪个接口初始化哪个,不看继承关系);
4、虚拟机启动时,会自动初始化带有main方法的类;
5、使用动态语言支持时,如果一个MethodHandle实例最后的解析结果是REF_getStatic、REF_putStatic、REF_invokeStatic的方法句柄且对应的类未初始化时(恕BZ学识浅薄,目前还没
理解这种情况对应实际代码中的哪种情形,只能先放放,好在这东西一般也遇不到 (><) )。
额外需要说明两点,这两点也经常在那种仿佛是考脑筋急转弯的编程题中遇到:一是在new一个引用类数组时不会触发这个类的初始化;二是对于常量的引用不会触发类初始化(static final)。
尤其是第二点要特别说明一下,如果A类中有一个常量叫VALUE,B类中引用了这个常量,那么在编译的时候,编译器会把这个VALUE直接放入B类的运行时常量池中供其后续使用,就是说在
编译之后,A类与B类已经没有任何交互了,所以也就不会触发初始化了。
二、类加载的各个过程简介
1、加载
类加载的第一个阶段叫加载,主要做的是三步:
1)、通过类的全限定名定位到对应的class文件;
2)、将二进制字节文件转化为方法区中的运行时数据;
3)、在内存中生成一个Class对象,作为方法区中访问运行时数据(即访问2)中数据)的入口。
此阶段自由度较高,我们可以自定义一个类加载器,加载class文件
2、验证
验证主要包括四部分:文件格式校验、源数据校验(包括语义校验)、字节码校验、字符引用校验
3、准备
在此阶段,虚拟机会为类变量(即static修饰的成员变量)分配内存并赋初始的默认值。例如一个类变量private static int a = 2,在此阶段中,会给赋初值,即a=0。实际的2这个值是在
初始化阶段赋予。而如果是static final类型的变量,在此阶段会直接赋终值。
4、解析
将要加载的那个类的运行时常量池内的符号引用替换为直接引用
5、初始化
初始化的过程就是执行类构造器<clinit>()方法的过程。此方法是在编译阶段由编译器收集类中的静态变量赋值动作、静态方法、静态块的语句合并而成的。
虚拟机会保证执行<clinit>()方法前会先执行父类的<clinit>方法,同样如果是接口则不用先执行父类的类构造器。
三、类加载器
Java中一共定义了三种类加载器:启动类加载器 <-- 扩展类加载器 <-- 应用程序类加载器,继承关系如箭头所示,而我们自定的类加载器,都是以应用程序类加载器为父类。
类加载器很重要,因为JVM中定义两个类是不是同一个类,只用两个判断条件:一个是类的全限定名是否相同,另一个是加载这个类的类加载器是否相同。如果类加载器不同,
即使类的全限定名一样,虚拟机一样会判定这是两个不同的类。
Java中的类加载器加载类,采用双亲委派模型,即类加载器C要加载类A时,会先让父加载器去加载,一直往上传递,除非父类加载器中搜不到这个类,才会让子类去加载,并且
每个类只能被加载一次。这样做的好处就是可以限定核心类不会被替换篡改。比如一种常见的面试题,如果你重新编写了一个路径为java.lang.String的类,能否调用到这个自定的类
中的方法?在这里很明显答案是不会,因为JVM中已经加载了那个系统的java.lang.String类,当用应用程序类加载器加载我们自定义的String类时,由于双亲委派模型的存在,加载
任务会被委派给父类,一直往上传递,最后到启动类加载器那里,然后发现已经加载过一次这个全路径名的类了,不能重复加载,所以自定义的String类就无法被加载调用了。(有没
有发现这个剧情跟真假美猴王很相似,一直传递到佛祖那,才辨别出了真假 。。。)
类加载就暂时到这里,书中还提到一些双亲委派模型被破坏的场景,由于了解的不够透彻,就先不乱发言了。学习之路,还是要坚持死磕啊,加油!
JVM的类加载的更多相关文章
- JVM学习一:JVM之类加载器概况
18年转眼就3月份都快结束了,也就是说一个季度就结束了:而我也因为年前笔记本坏了,今天刚修好了,那么也应该继续学习和博客之旅了.今年的博客之旅,从JVM开始学起,下面我们就言归正传,进入正题. 一.J ...
- (转) JVM——Java类加载机制总结
背景:对java类的加载机制,一直都是模糊的理解,这篇文章看下来清晰易懂. 转载:http://blog.csdn.net/seu_calvin/article/details/52301541 1. ...
- JVM自定义类加载器加载指定classPath下的所有class及jar
一.JVM中的类加载器类型 从Java虚拟机的角度讲,只有两种不同的类加载器:启动类加载器和其他类加载器. 1.启动类加载器(Boostrap ClassLoader):这个是由c++实现的,主要负责 ...
- JVM内存结构 JVM的类加载机制
JVM内存结构: 1.java虚拟机栈:存放的是对象的引用(指针)和局部变量 2.程序计数器:每个线程都有一个程序计数器,跟踪代码运行到哪个位置了 3.堆:对象.数组 4.方法区:字节流(字节码文件) ...
- JVM之类加载机制
JVM之类加载机制 JVM类加载机制分为五个部分:加载,验证,准备,解析,初始化,下面我们就分别来看一下这五个过程. 类加载五部分 加载 加载是类加载过程中的一个阶段,这个阶段会在内存中生成一个代表这 ...
- JVM——自定义类加载器
)以上两种情况在实际中的综合运用:比如你的应用需要通过网络来传输 Java 类的字节码,为了安全性,这些字节码经过了加密处理.这个时候你就需要自定义类加载器来从某个网络地址上读取加密后的字节代码,接着 ...
- 深入理解JVM的类加载
前言: 前面又说到Java程序实际上是将.class文件放入JVM中运行.虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验,转换,解析和初始化,最终形成可以被虚拟机直接使用的Java类 ...
- JVM的类加载机制全面解析
什么是类加载机制 JVM把描述类的数据从Class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被JVM直接使用的Java类型,这就是JVM的类加载机制. 如果你对Class文件的结 ...
- JVM的类加载过程以及双亲委派模型详解
JVM的类加载过程以及双亲委派模型详解 这篇文章主要介绍了JVM的类加载过程以及双亲委派模型详解,类加载器就是根据指定全限定名称将 class 文件加载到 JVM 内存,然后再转化为 class 对象 ...
随机推荐
- H5新特性-canvas绘图--渐变对象路径(最复杂)--图片--变形操作
今天的目标 3.1:canvas绘图--(重点掌握:渐变对象.路径.图片.变形) 3.2:canvas绘图--渐变对象 线性渐变: linearGradient 径向渐变: var g = ctx.c ...
- android各种笔记
一.生成key http://blog.csdn.net/anyanyan07/article/details/53493785 二.mac os项目变大 删除 项目中app->build文件夹 ...
- s6-6 TCP 连接释放
TCP 连接释放 任何一方在没有数据要传送的时候,都可以发送一个FIN置位了的 TCP 数据段 当FIN被确认的时候,该方向的连接被关闭 当双向连接都关闭了的时候,连接释放 两军队问题 两军队问题 ( ...
- Python request库与爬虫框架
Requests库的7个主要方法 requests.request():构造一个请求,支持以下各方法的基础方法 requests.get():获取HTML网页的主要方法,对应于HTTP的GET ...
- 《python语言程序设计》_第二章笔记
#2.2_编写一个简单的程序 项目1: 设计:radius=20,求面积area? 程序: radius=20 #给变量radius复制area=radius*radius*3.14159 #编写ar ...
- text-decoration:[ text-decoration-line ] || [ text-decoration-style ] || [ text-decoration-color ] 默认值:
css3中字体装饰,多样化的界面效果,: [ text-decoration-line ]:指定文本装饰的种类.相当于CSS2.1的 text-decoration 属性, 可取值:none | un ...
- Openvswitch手册(8): ovs-vsctl的DB的操作
ovs-vsctl的DB的操作 如果你在命令行里面找不到相应的命令创建和删除对象,则可以直接删除数据库 [−−if−exists] [−−columns=column[,column]...] lis ...
- AVPass技术分析:银行劫持类病毒鼻祖BankBot再度来袭,如何绕过谷歌play的杀毒引擎?
背景 近期,一批伪装成flashlight.vides和game的应用,发布在google play官方应用商店.经钱盾反诈实验室研究发现,该批恶意应用属于新型BankBot.Bankbot家族算得上 ...
- 快速制作U盘启动盘和U盘安装盘的方法
制作U盘启动盘的方法: 1. 安装UltraISO; 2. 安装完成后,用管理员权限打开UltraISO; 3. 打开启动盘文件,一般为ISO文件: 4. 插入U盘: 5. 选择 启动 -> 写 ...
- Dubbo 源码分析 - 服务调用过程
注: 本系列文章已捐赠给 Dubbo 社区,你也可以在 Dubbo 官方文档中阅读本系列文章. 1. 简介 在前面的文章中,我们分析了 Dubbo SPI.服务导出与引入.以及集群容错方面的代码.经过 ...