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 ...
随机推荐
- flask 运行 flask db init 报错,init-db 命令找不到
flask init-db 结果是 `Error: No such command “init-db”. 那是因为init-db 已经被 flask db init 给代替了 运行 flask db ...
- (转)Nginx中sendfile的作用
原文:https://blog.csdn.net/zhusixun/article/details/81702380 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上 ...
- MySQL Shared and Exclusive Locks
官方文档 InnoDB implements standard row-level locking where there are two types of locks, shared (S) loc ...
- 转 Oracle 同一个字段的两值进行加减计算
https://www.cnblogs.com/hjianguo/p/6041617.html 如 病人ID 入院日期 出院日期 00001 2016 ...
- TCP报文结构
来自:https://blog.csdn.net/qq_32998153/article/details/79680704
- 大数据 -- Hadoop集群环境搭建
首先我们来认识一下HDFS, HDFS(Hadoop Distributed File System )Hadoop分布式文件系统.它其实是将一个大文件分成若干块保存在不同服务器的多个节点中.通过联网 ...
- vue脚手架中使用Vant,实现自动按需引入组件,并将px转换为rem
偶然间看到一款不错的移动端vue组件库Vant,照着官方文档敲了一下,感觉还是不错的.想着以后的项目中可能会运用到,特此记录下,方便之后使用. 现在很多的组件库为了减小代码包体积,都支持按需加载了.V ...
- javascript下載csv檔案
參考自: https://dotblogs.com.tw/shihgogo/2017/05/31/090831 function createCsvFile(){ var fileName = &qu ...
- Tomcat总结四种部署方式
静态部署 一.Webapps 把项目复制到Tomcat的Webapps 把war包复制到Tomcat的Webapps下 *修改Webapps的默认路径: * Tomcat的conf目录下的server ...
- firewall详解
官方文档介绍地址:https: //access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/Security_Gui ...