深入理解JVM(9)——类加载的过程
加载是类加载的第一步。
一、加载
a)加载的过程
1)通过一个类的全限定名获取这个类的二进制字节流,也就是class文件
2)将二进制字节流的存储结构转换为特定的数据结构,存储在方法区
3)在内存中创建一个Java.lang.Class的对象,接下来在程序运行的过程中所有对这个类的访问都是通过这个Class类型的对象进行访问的。
b)从那里加载二进制字节流
1) 一般的二进制字节流都是通过已经编译好的本地class文件中进行加载
2) 从压缩文件中进行加载
3)从网络中进行加载
4)从数据库中进行加载
5) 通过其他文件动态生成
c)普通类的加载和数组类加载过程的区别
数组也是一种数据类型,成为数组类型。String[] str = new String[10];这是一个数组类型,只不过是该数组的数据元素是String类型,在程序运行过程中当遇到new需要创建一个数组的时候,JVM会首先创建一个数组类,然后再由类加载器创建数组中的元素类;但是普通类的创建过程就是直接由类加载器创建。
d) 加载过程的注意点
1) JVM并没有给出类在方法区存放的数据结构
2) JVM并没有给出Class对象的存放位置
3) 加载阶段和连接阶段是交叉进行的,类加载过程中每个步骤的开始顺序有要求限制,但是并没有规定每个步骤的结束顺序
二、验证
a)验证的目的:保证二进制字节流中的二进制信息符合JVM的规范,不会出现安全问题。
b)为什么需要验证:
Java是一门安全语言,他能确保程序员不会访问数组之外的内存、不会把一个对象转换成任意类型、能避免代码跳转到一个不存在的地方,如果出现这样的情况,编译过程就会报错,这就是说Java语言的安全性是通过编译器实现的。
我们知道编译器和虚拟机是两个相互独立的部分,虚拟机只认二进制字节码,但是它不关心二进制字节码的来源,如果是Java编译器生成的二进制字节码,那么就会相对的安全,但是还能通过其他的途径获取到二进制字节码,这样的二进制字节码是没办法保证符合JVM规范的,为了防止二进制字节流中出现安全问题,因此需要验证。
c) 验证的过程:
1)文件格式的验证
2)元数据的验证
3)字节码的验证
4) 符号引用的验证
三、准备:
a) 为已经在方法区中的类的静态成员变量分配内存
b)为静态成员变量设置初始值(默认初始化)
四、解析:是虚拟机将常量池中的符号引用变为直接引用的过程
五、 初始化:就是执行类构造器Clinit()方法的过程。Clinit()方法是编译器自动产生的,收集类中静态代码块中的类成员变量赋值语句和类的静态成员变量赋值语句。在准备阶段,类的静态成员变量已经被默认初始化,但是在初始化阶段需要进行显示的初始化。
六、初始化过程中需要注意的点:
a)clinit()方法对类中的静态成员变量赋值的顺序是根据代码中成员变量出现的顺序进行赋值的;
b)静态代码块能够访问在静态代码块之前出现的类的静态成员变量,在其后的静态成员变量不能被访问
c)静态代码块能够为出现在其后的静态成员变量赋值
d)构造函数init()需要显示的调用父类的构造器,但是类的clinit()方法不用调用父类的这个方法,因为虚拟机会保证在执行这个类的clinit()方法之前已经执行了父类的这个方法。
e)如果在接口/类中没有静态代码块也没有类的静态成员变量的话,那么编译器就不会生成clinit()方法
f)接口中只会出现静态成员变量,不会出现静态代码块,如果出现静态成员变量的话,编译器就会自动生成一个clinit()方法
g)接口在执行clinit()方法的时候不会确保其父接口的clinit()方法已经被执行,只有当父接口中的静态成员变量被执行到的时候才会执行父接口的clinit()方法。
h) 虚拟机会给clinit()方法上锁,当多个线程同时执行某一个类的clinit()方法的时候,只能有一个线程能够正常执行,其他的线程会被阻塞,并且只要这个类的clinit()方法已经被执行过之后,其他的线程就不能在执行,这样也就保证了在同一个类加载器下一个类只能被初始化一次。
深入理解JVM(9)——类加载的过程的更多相关文章
- 【深入理解JVM】类加载器与双亲委派模型 (转)
出处: [深入理解JVM]类加载器与双亲委派模型 加载类的开放性 类加载器(ClassLoader)是Java语言的一项创新,也是Java流行的一个重要原因.在类加载的第一阶段“加载”过程中,需要通过 ...
- 深入理解JVM之类加载
---title: [学习]深入理解JVM之类加载.mddate: 2019-10-20 22:20:06tags: JVM 类加载--- Java类的加载,连接,初始化都是在程序运行期间执行的 ## ...
- 深入理解JVM的类加载
前言: 前面又说到Java程序实际上是将.class文件放入JVM中运行.虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验,转换,解析和初始化,最终形成可以被虚拟机直接使用的Java类 ...
- JVM实战---类加载的过程
任何程序都需要加载到内存才能与CPU进行交流 同理, 字节码.class文件同样需要加载到内存中,才可以实例化类 ClassLoader的使命就是提前加载.class 类文件到内存中 在加载类时,使用 ...
- 理解JVM之类加载机制
类完整的生命周期包括加载,验证,准备,解析,初始化,使用,卸载,七个阶段.其中验证,准备,解析统称为连接,类的卸载在前面的关于垃圾回收的博文中已经介绍. 加载,验证,准备,初始化,卸载这五个阶段的顺序 ...
- 【深入理解JVM】类加载器与双亲委派模型
原文链接:http://blog.csdn.net/u011080472/article/details/51332866,http://www.cnblogs.com/lanxuezaipiao/p ...
- 深入理解JVM(3)——类加载机制
1.类加载时机 类的整个生命周期包括了:加载( Loading ).验证( Verification ).准备( Preparation ).解析( Resolution ).初始化( Initial ...
- 深入理解JVM一类加载器原理
我们知道我们编写的java代码,会经过编译器编译成字节码文件(class文件),再把字节码文件装载到JVM中,映射到各个内存区域中,我们的程序就可以在内存中运行了.那么字节码文件是怎样装载到JVM中的 ...
- 深入理解JVM - 虚拟机类加载机制 - 第七章
类加载的时机类从被加载到虚拟机内存开始,到卸载出内存为止,它的整个生命周期包括了:加载/验证/准备/解析/初始化/使用/卸载七个阶段.其中验证/准备和解析统称为连接(Linking). 加载.验证.准 ...
- 深入理解JVM,类加载器
虚拟机设计团队把类加载阶段中的“通过一个类的全限定名来获取描述此类的二进制字节流(即字节码)”这个动作放到Java虚拟机外部去实现,以便让应用程序自己决定如何去获取所需要的类.实现这个动作的代码模块称 ...
随机推荐
- [转]解决-Dmaven.multiModuleProjectDirectory system property is not set. Check $M2_HOME environment variable and mvn script match.
来源:http://www.cnblogs.com/sprinng/p/5141233.html 1.添加M2_HOME的环境变量 2.Preference->Java->Installe ...
- Windows下80端口被进程System占用的解决方法
最近电脑时不时就发生了80端口被占用的情况,简单百度解决后,当重启电脑的时候又发生被占用的情况.今天非常幸运的是,发生了80端口和8080端口都被占用了情况,忍无可忍决定下定决心解决这个坑爹的问题,经 ...
- 修改ini文件的批处理
用VBS更简单: vbs代码: On Error Resume Next Dim Fso,TxtFl,Str Set Fso = CreateObject("Scripting.FileSy ...
- 通过awk获取netstat命令中的进程号
需要如下: 获取进程号
- 使用ycsb对hbase1.4.9 benchmark
Ycsb下载地址:https://github.com/brianfrankcooper/YCSB/releases 目前测试hbase1.4.9,因此下载ycsb-hbase14-binding-0 ...
- BZOJ3286 Fibonacci矩阵 矩阵 快速幂 卡常
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ3286 题意概括 n,m,a,b,c,d,e,f<=10^1000000 题解 神奇的卡常题目 ...
- python 多线程锁机制
GIL(全局解释器锁) GIL并不是Python的特性,它是在实现Python解析器(CPython)时所引入的一个概念,是为了实现不同线程对共享资源访问的互斥,才引入了GIL 在Cpython解释器 ...
- python 条件与循环
一.if语句 1.1 功能 计算机又被称作电脑,意指计算机可以像人脑一样,根据周围环境条件(即expession)的变化做出不同的反应(即执行代码) if语句就是来控制计算机实现这一功能 1. ...
- C# ImageHelper
using System; using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.Web; ...
- JS获取IOS版本号
var str= navigator.userAgent.toLowerCase(); var ver=str.match(/cpu iphone os (.*?) like mac os/); if ...