JVM中的类加载
JVM中的类加载
关于JVM中类的加载这部分知识在网上有太多的文章描述这部分的知识。但是多数文章都过于冗长,难以理解。这篇文章主要是一些我对JVM中类的加载的理解。
一、一句话概括
java在类加载的时候实际上就是把xxx.class文件读入JVM方法去,并在内存中生成class的对象。
二、那么Java中是怎么加载类的
1. 首先我们要了解类加载器
java 中有四种类加载器。从底向上依次是
- BootStrapClassLoader: 负责加载 JAVA_HOME\lib 目录中的,或通过-Xbootclasspath参数指定路径中的,且被虚拟机认可(按文件名识别,如rt.jar)的类。
- ExtensionClassLoader: 负责加载 JAVA_HOME\lib\ext 目录中的,或通过java.ext.dirs系统变量指定路径中的类库。
- ApplicationClassLoader: 负责加载用户路径(classpath)上的类库。
- UserClassLoader:用户自定义的ClassLoader。
2. 类加载器是怎么加载类的
类加载器是通过双亲委派机制来加载类的
2.1 什么是双亲委派机制?
类加载器在接收到类加载请求之后,低等级的ClassLoader会首先检查这个类是否已经加载过了,若是没有加载则,将加载的请求委派给双亲(比如 ApplicationClassLoader会将请求委派给ExtensionClassLoader)。这样一层一层的传送直到BootStrapClassLoader,如果BootStrapClassLoader没有找到,则逐级向下反馈,下级再寻找该类试图加载。
2.2 为什么使用双亲委派机制?双亲委派机制的好处?
- JVM只有在两个类的类名和加载它的类加载器均相同的情况下才会判定这两个类相同。若不采用双亲委派机制,则有可能造成一个类被多个不同的类加载器加载,这样会被识别为几个相互不同的类,相互之间赋值会出现问题。
- 双亲委派机制能保证多加载器加载某个类时,最终都是由一个加载器加载,确保最终加载结果相同。
3. 类加载的过程中哪些代码会被执行到?
静态代码块以及静态变量 这些内容只被执行一次,因此他们在内容中的位置是相对固定的。所以被叫做静态。用这样的概念来解释静态变量:
- 静态变量:是代码中用static关键字修饰,告诉JVM,该变量只在内存中存在一份,该引用存在方法区且地址是相对固定不变的所以称作“静态变量”。
三、类加载的具体过程
1. 加载(loading)
加载阶段主要完成的是将虚拟机外部的二进制字节流按照JVM所需的格式存储在方法区中。
- 通过一个全限定名获取二进制字节流。
- 将二进制中的静态存储结构转化为方法区的运行时数据结构。
- 在内存中生成一个代表这个类的Class对象,作为方法区数据的访问接口。
2.验证(verification)
验证作用是确保文件的字节流包含信息符合当前虚拟机要求,保证其并不会危害虚拟机的安全。
验证的主要内容为:
- 文件格式验证:
这一步主要是保证Class文件格式上符合Java信息的要求。例如文件类型,版本号,常量池,常量池数据等等。
注:在这一步字节流就会进入内存的方法区之中了,后面的操作都是基于方法区内的存储结构进行的。- 元数据验证:
对字节码描述信息进行语义分析,例如类是否有父类,重载是否正确,final,abstract有没有用错等,其主要目的是对类的元数据进行语义分析,保证符合Java语言规范。- 字节码验证:
对数据流和控制流进行分析。例如字节码指令集的正确,程序跳转的安全。其主要目的是检查方法体内的数据安全,确保程序语义合法,符合逻辑。符号引用验证:
符号引用验证也是一个比较特殊的阶段,其为解析阶段服务(这也验证了前面所说的,这几个过程并不是依次执行完成的)。在解析过程中,虚拟机将符号引用转换为直接引用,其主要是对常量池中的各种符号引用做匹配性校验。检验内容包括以下几个:
- 符号引用指向的类能否找到。
- 指定的类有没有描述的方法和字段。
- 符号引用指向的各种信息的访问权限是不是对的。
3. 准备(preparation)
为类变量(被static修饰的变量)分配内存并设置类变量初始值。这里需要注意的是设初始值值得是为其设置零值,例如数值量的 0,boolean 值的 false 等。但是特殊情况下,如类变量是一个常量,那么在准备阶段,虚拟机就会将其设置为常量指代的值。
4. 解析 (resolution)
在验证阶段的符号引用验证说过解析阶段就是将符号引用转换为直接引用,那么符号引用和直接引用分别指什么呢,他们之间又有何区别:
- 符号引用。是能够无歧义定位目标的任何形式的字面量,其与虚拟机实现的内存布局无关,引用的目标不一定需要加载入内存中;
- 直接引用。可以直接指向目标指针,偏移量的引用,其和虚拟机实现的内存布局相关,引用的目标一定需要在内存中。
在这一步虚拟机会将类/接口,字段,类方法,接口方法等进行解析,变为直接引用。
5. 初始化(initialization)
初始化阶段主要是初始化类变量和其他资源,主要是通过()方法。
()是通过编译器自动收集所有类变量的赋值动作和静态语句块(static{}块)并按照顺序合并生成的。
5.1 什么时候JVM进行初始化?
- 在字节码层面遇到以下指令时,new(对象都要生成了,肯定要初始化了),get/put static(使用静态变量了,肯定要赋值了),invoke static(调用静态方法了都,肯定要为静态量赋值);
- 反射调用。当使用java。lang。reflect中的方法对类进行反射调用;
- 初始化一个类的时候,发现父类还有初始化,那么需要先初始化其父类,(父接口不用立即初始化,只有使用到其常量时,才需要将其初始化);
- 虚拟机需要一个入口,因此主类需要初始化;
- 动态方法解析,解析出方法是其他类的静态方法,那么需要将其初始化。
JVM中的类加载的更多相关文章
- Java面试题:JVM中的类加载机制
JVM 的类加载机制是指 JVM 把描述类的数据从 .class 文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的 Java 类型,这就是 JVM 的类加载机制. 类 ...
- Java中的类加载器以及Tomcat的类加载机制
在加载阶段,虚拟机需要完成以下三件事情: 1.通过一个类的全限定名来获取其定义的二进制字节流. 2.将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构. 3.在Java堆中生成一个代表这个类 ...
- jvm之java类加载机制和类加载器(ClassLoader),方法区结构,堆中实例对象结构的详解
一.类加载或类初始化:当程序主动使用某个类时,如果该类还未被加载到内存中,则JVM会通过加载.连接.初始化3个步骤来对该类进行初始化.如果没有意外,JVM将会连续完成3个步骤. 二.类加载时机: 1 ...
- JVM中类加载器的父委托机制
类加载器 类加载器用来把类加载到Java虚拟机中. 类加载器的类型 有两种类型的类加载器: 1.JVM自带的加载器: 根类加载器(Bootstrap) 扩展类加载器(Extension) 系统类加载器 ...
- Java虚拟机JVM学习05 类加载器的父委托机制
Java虚拟机JVM学习05 类加载器的父委托机制 类加载器 类加载器用来把类加载到Java虚拟机中. 类加载器的类型 有两种类型的类加载器: 1.JVM自带的加载器: 根类加载器(Bootstrap ...
- Java中的类加载器
转载:http://blog.csdn.net/zhangjg_blog/article/details/16102131 从java的动态性到类加载机制 我们知道,Java是一种动态语言.那么怎 ...
- tomcat 7 中的类加载器学习
tomcat 7自带很多junit测试用例,可以帮助我们窥探源码的秘密.以下使用来测试类加载器的一个测试用例.类加载器也是对象,他们用来将类从类从.class文件加载到虚拟机,这些已经讲了很多,深入j ...
- 你需要简单了解JVM中的内存长什么样子
下面有关JVM内存,说法错误的是? 1.程序计数器是一个比较小的内存区域,用于指示当前线程所执行的字节码执行到了第几行,是线程隔离的 2.Java方法执行内存模型,用于存储局部变量,操作数栈,动态链接 ...
- JVM学习之类加载
该文使用Hotspot JDK1.7 一.类加载器 1.什么是类加载器 类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java ...
随机推荐
- MQTT研究之EMQ:【EMQX使用中的一些问题记录(1)】
issue 1. EMQX的共享订阅 EMQX是一个非常强大的物联网通信消息总线,基于EMQX开展应用开发,要注意很多配置细节问题,这里要说到的就是共享订阅以及和cleanSession之间的关系问题 ...
- 基于redis5的session共享:【redis 5.x集群应用研究】
基于springsession构建一个session共享的模块. 这里,基于redis的集群(Redis-5.0.3版本),为了解决整个物联网平台的各个子系统之间共享session需求,且方便各个子系 ...
- C++排序算法比较
排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存. 我们这里说说八大排序就是内部排序. ...
- DevExpress XtraReport - 动态加载报表布局模板
XtraReport的报表模板文件是.repx,下面的代码演示动态加载报表布局模板. XtraReport mReport = new XtraReport(); mReport.LoadLayout ...
- javascript之this、new、apply和call详解
this指针的原理是个很复杂的问题,如果我们从javascript里this的实现机制来说明this,很多朋友可能会越来越糊涂,因此本篇打算换一个思路从应用的角度来讲解this指针,从这个角度理解th ...
- 服务器端debug操作
写好的代码打个包放在服务器上,发现与理想的情况下不一致.查看log日志又觉得很烦,毕竟debug调试才是王道. 下面来说说怎么debug调试服务器上的.最好服务器上的代码和本地的保存一致,这样误差会小 ...
- chrome的无头(headless)模式
chrome的无头(headless)模式 用selenium调用phantomjs浏览器的方式几乎可以爬取任何网站,但是与调用chrome相比,phantomjs的稳定性还是不够.如果能让chrom ...
- RestTemplate支持GET方法携带Body信息
首先必须声明: GET方法支持通过Body携带参数(HTTP1.1开始支持) 但是默认的RestTemplate是不支持滴!原因如下: RestTemplate支持通过setRequestFactor ...
- 嵌入式02 STM32 实验10 定时器中断
优秀文章 https://blog.csdn.net/qq_38351824/article/details/82619734 一.STM32通用定时器(TIM2.TIM3.TIM4和TIM5共四个通 ...
- Tarjan求有向图强连通分量 BY:优少
Tarjan算法:一种由Robert Tarjan提出的求解有向图强连通分量的线性时间的算法. 定义给出之后,让我们进入算法的学习... [情境引入] [HAOI2006受欢迎的牛] 题目描述: 每头 ...