理解JVM之类加载机制
类完整的生命周期包括加载,验证,准备,解析,初始化,使用,卸载,七个阶段.其中验证,准备,解析统称为连接,类的卸载在前面的关于垃圾回收的博文中已经介绍.
加载,验证,准备,初始化,卸载这五个阶段的顺序是确定的,类的加载必须按照这种顺序按部就班的来,而解析阶段不一定,它可以在初始化阶段之后开始,这是为了支持java的运行时动态绑定.值得注意的是,上述的五个阶段只是按部就班的"开始",并不是按部就班的"进行"或者"完成",因为这些阶段通常是互相交叉混合进行的,通常会在一个阶段执行的过程调用,激活另一个阶段.
在java虚拟机规范中并没有进行强制约束什么时候加载类,这是交给虚拟机具体实现自由把握,但是对于初始化阶段,虚拟机规范有严格规定:
1.使用new实例化对象或者读取,设置一个类的静态字段(被final或者已在编译器吧结果放入常量池的静态字段除外)的时候以及调用一个类的静态方法的时候.
2.使用反射调用的时候,如果类没初始化,需要进行初始化
3,当初始化一个类的时候,父类没有初始化,则需要先初始化父类
4.虚拟机启动时,用户需要制定一个执行类(包含main方法的那个类),虚拟机会先初始化这个主类.
5.使用动态语言支持时,如果一个java.lang.MethodHandle实例最后解析结果REF_getStatic,REF_putStatic,REF_invokeStatic的方法句柄,并且这个句柄锁对应的类没有初始化,则初始化这个类.
下面具体介绍类加载的过程.
1.加载
加载阶段,虚拟机需要完成3件事情:
1) 通过一个类的全限定名来获取定义此类的二进制字节流
2) 将这个字节流锁代表的静态存储结构转化为方法区的运行时数据结构
3) 在内存中生成带包这个类的Class对象,作为方法区这个类的各种数据访问入口.
对于数组类而言,情况不同,数组类本身不通过类加载器创建,它是由java虚拟机直接创建.数组类的创建过程遵循以下规则:
1) 如果数组的组件类型(指数组去掉一个维度的类型)是引用类,那就采取上述的方法来加载这个组件类型,数组C将在加载该组件类型的类加载器的类名空间上被标识
2) 如果数组的组件类型不是引用类型(例如int[]),虚拟机会将数组标记为与引导类加载器关联
3) 数组类的可见性与他的组件类型的可见性一直,如果组件类型不是引用类型,那数组类的可见性将默认为public.
加载完成后,外部二进制字节流就按照虚拟机需要的格式存储在方法区中,然后实例化一个Class类的对象作为程序访问方法区中的这些类型数据的外部接口.
2.验证
验证是连接的第一步,这一阶段为了确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全.验证分为四个阶段:文件格式验证,元数据验证,字节码验证,符号引用验证
1) 文件格式验证是验证字节流是否符合Class文件格式的规范,并且能够被当前版本的处理机处理.
2) 元数据验证是对字节码描述的信息进行语义分析,以保证其描述的信息符合java语言规范的要求.
3) 字节码验证是只能怪过验证过程最复杂的阶段,主要是通过数流和控制流分析,确定程序语义是合法的,符合逻辑的.这个阶段对类的方法体进行校验分析,保证被校验类的方法在运行时不会出现危害虚拟机安全的事件.
4) 符号引用验证发生在虚拟机将符号引用转化为直接引用的时候.这个动作是在解析阶段发生.
3.准备
这个阶段是正式为类变量分配内存并设置类变量初始值的阶段,这些变量锁使用的内存都在方法区中分配.值得注意的是这里进行分配内存的仅包括类变量(被static修饰的变量),不包括实例变量,其次这里设置初始值是将值设为零值,例如一个整型类变量设置的零值是0,而不是代码中写出来的值.将代码写出来的值赋值给这个变量是初始化阶段做的事情
4.解析
解析阶段是虚拟机将常量池的符号引用替换为直接引用的过程.解析包括类或接口的解析,字段解析,类方法解析,接口方法解析
5.初始化
初始化是类加载的最后一步,在准备阶段,变量已经赋过一次系统要求的初始值,而在初始化阶段,则根据程序员通过程序制定的主观计划去初始化类变量和其他资源,或者换一种说法:初始化阶段是执行类构造器<clinit>()方法的过程.
<cliinit>()方法时由编译器自动收集所有类变量的赋值动作和静态语句快中的语句合并产生的,收集的顺序是由语句在源文件中出现的顺序决定的,静态语句块只能访问到定义域在静态语句块之前的变量,后面的变量只能赋值,不能访问.
<cliinit>()方法还有许多规定,请自行查找相关资料
6.类与类加载器
类加载器虽然只用于实现类加载动作,但是在java程序中的还有其他作用.对于任意一个类加载器,都有一个独立的类名空间,而被这个类加载器加载出来的类,其类名会被标记上类加载器的类名空间,则两个特性决定了一个类在虚拟机中的唯一性.也就是说我们要比较两个类是否相等,前提是要这两个类是同一个类加载器加载出来的.否则就算是同一个class文件加载出来的这两个的也是不相等的.因为instanceof这个关键字会将两个类判定为不是同一个类,
7.双亲委派模型
这个模型的工作过程是:如果一个类加载器收到了类加载请求,它首先不会自己尝试加载这个类,而是吧这个请求委派给父类加载器去完成.因此所有的加载请求最终都会送到顶层的启动类加载器,只有父类反馈无法完成类加载让子加载器才会尝试加载.这个模型使java的类不会因为类加载器不同而产生不同的相同类.
理解JVM之类加载机制的更多相关文章
- 深入理解JVM(3)——类加载机制
1.类加载时机 类的整个生命周期包括了:加载( Loading ).验证( Verification ).准备( Preparation ).解析( Resolution ).初始化( Initial ...
- 深入理解JVM - 虚拟机类加载机制 - 第七章
类加载的时机类从被加载到虚拟机内存开始,到卸载出内存为止,它的整个生命周期包括了:加载/验证/准备/解析/初始化/使用/卸载七个阶段.其中验证/准备和解析统称为连接(Linking). 加载.验证.准 ...
- 深入理解JVM的类加载
前言: 前面又说到Java程序实际上是将.class文件放入JVM中运行.虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验,转换,解析和初始化,最终形成可以被虚拟机直接使用的Java类 ...
- 【深入理解JVM】类加载器与双亲委派模型 (转)
出处: [深入理解JVM]类加载器与双亲委派模型 加载类的开放性 类加载器(ClassLoader)是Java语言的一项创新,也是Java流行的一个重要原因.在类加载的第一阶段“加载”过程中,需要通过 ...
- 大白话谈JVM的类加载机制
前言 我们很多小伙伴平时都是做JAVA开发的,那么作为一名合格的工程师,你是否有仔细的思考过JVM的运行原理呢. 如果懂得了JVM的运行原理和内存模型,像是一些JVM调优.垃圾回收机制等等的问题我们才 ...
- 一文教你读懂JVM的类加载机制
Java运行程序又被称为WORA(Write Once Run Anywhere,在任何地方运行只需写入一次),意味着我们程序员小哥哥可以在任何一个系统上开发Java程序,但是却可以在所有系统上畅通运 ...
- JVM内存结构 JVM的类加载机制
JVM内存结构: 1.java虚拟机栈:存放的是对象的引用(指针)和局部变量 2.程序计数器:每个线程都有一个程序计数器,跟踪代码运行到哪个位置了 3.堆:对象.数组 4.方法区:字节流(字节码文件) ...
- JVM之类加载机制
JVM之类加载机制 JVM类加载机制分为五个部分:加载,验证,准备,解析,初始化,下面我们就分别来看一下这五个过程. 类加载五部分 加载 加载是类加载过程中的一个阶段,这个阶段会在内存中生成一个代表这 ...
- JVM的类加载机制全面解析
什么是类加载机制 JVM把描述类的数据从Class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被JVM直接使用的Java类型,这就是JVM的类加载机制. 如果你对Class文件的结 ...
随机推荐
- Qt Http get
1.直接建立连接,向网站发送http请求 QNetworkAccessManager *accessManager = new QNetworkAccessManager(this); connect ...
- 今天被这个BDE错误搞了半天,不过终于好了,分享一下
今天正编译程序时,突然就报了这个错误出来,重启电脑都没用,多亏网上高手指教,先把解决方案列于下,供受此累得朋友查阅,自己也留底供查找:"Shared memory conflict ($21 ...
- vue react 路由history模式刷新404问题解决方案
vue单页因微信分享和自动登录需要,对于URL中存在’#’的地址,处理起来比较坑.用history模式就不会存在这样的问题.但是换成history模式,就会有个新的问题,就是页面刷新后,页面就无法显示 ...
- 软件测试成熟度模型TCMM (转载)
下面我们就看看是如何划分的,来评判一下各位同仁自己所在的公司,所在的级别. TCMM Level 1:Initial(初始级) 测试处于一个混乱的状态,还不能把测试同调试分开,在编码完成后才进行测 ...
- RobotFramework: 接口测试时,注意请求体content-type
使用Post Request关键字时 1.如果请求体的content-type为:application/x-www-form-urlencoded,则传参数时需要给params参数赋值 2.如果co ...
- mysql数据库建表授权操作
1.create schema [数据库名称] default character set utf8 collate utf8_general_ci;--创建数据库 采用create schema和c ...
- phar缓存 编译缓存 提高phar文件包加载速度
phar文件可以把用到的PHP文件全部打包在一个文件中,十分方便网站部署.但是单个的PHP文件可以使用opcache缓存(字节码缓存),以提升PHP的运行速度.那么PHAR文件包如何使用缓存呢. 这里 ...
- Vue简单基础 + 实例 及 组件通信
vue的双向绑定原理:Object.defineProperty() vue实现数据双向绑定主要是:采用数据劫持结合发布者-订阅者模式的方式,通过 Object.defineProperty() 来劫 ...
- 了解 Selenium 定位方式
※元素定位的重要性:在于查找元素 And 执行元素 定位元素的三种方法 1.定位单个元素:在定位单个元素时,selenium-webdriver 提示了如下一些方法对元素进行定位.在这些定位方式中,优 ...
- Java中的IO流之输出流|乐字节
大家好,乐字节小乐又来了.上一篇给大家带来的是:Java中的IO流之输入流|乐字节,本文将继续讲述IO流之输出流. 一.输出流 1.抽象类:OutputStream 和 Writer Output ...