java虚拟机类加载
java虚拟机中类的加载

(JVM的大致结构图)
从发class文件到内存中的类,按先后顺序,需要经过加载,链接以及初始化三大步骤。
java语言的类型可分为两大类:基本类型(primitive type)和引用类型(references type)
基本类型:是由java虚拟机预先定义好的。
引用类型:Java将其细分为四种,类、接口、数组类和泛型参数。
由于泛型参数会在编译过程中被擦除(泛型类型在逻辑上可以看成是多个不同的类型,实际上都是相同的基本类型。),因此Java虚拟机实际上只有前三种。在类、接口和数组类中,数组类是由java虚拟机直接生成的,其他两种则有对应的字节流。
字节流:最常见的形式要属由Java编译器生成的class文件。除此之外,我们也可以在程序内部直接生成,或者从网络中获取字节流。这些不同形式的字节流,都会被加载到java虚拟机中,称为类或者接口。
无论是直接生成的数组类,还是加载的类,java虚拟机都要对其进行链接和初始化。
加载
加载是指查找字节流,并且据此创建类的过程。对于类来说,java虚拟机需要借助类加载器来完成查找字节流的过程。
当JVM启动时,会形成由三个类加载器组成的初始类加载器层次结构:
1、启动类加载器(BootstrapClassLoader):是嵌在JVM内核中的加载器,它是由C++实现的,没有对应的java对象,因此在java中只能用null来代替。它主要负责加载JAVA_HOME/lib下的类库,启动类加载器无法被应用程序直接使用。
除了启动类加载器外,其他的类加载器都是java.lang.ClassLoader的子类,因此有对应的java对象。这些类加载器需要先由另一个类加载器,比如说启动了加载器,加载至java虚拟机中,方能执行类加载。
在Java9之前,启动类加载器负责加载最为基础,最为重要的类,比如存放在jre的lib目录下的jar包(以及由虚拟机参数-Xbootclasspath指定的类)。除了启动类加载器之外,另外两个重要的类加载器是扩展类加载起(extension class loader)和应用类加载器(application class loader),均由java核心类库提供。
2、扩展类加载器(extension class loader):其父类是启动类加载器,他负责加载相对次要、但又通用的类,比如存放在jre的lib/ext目录下的jar包中的类(以及由系统变量java.ext.dirs指定的类)。
3、应用类加载器(application class loader):其父类是扩展类加载器,它负责加载用用程序下的类。(这里的应用程序路径,便是指虚拟机参数-cp/-classpath、系统变量CLASSPATH所制定的路径。)默认情况下,应用程序中包含的类是由应用类加载器加载的。
java9引入了模块系统,,并且略微更改了上述的类加载器,扩展类加载器被改名为平台类加载器(platform class loader)。Java SE 中除了少数几个关键模块,比如说、java.base是由启动类加载器加载之类,其他的模块均由平台加载器所加载。
除了java核心类库提供的类加载器之外,我们还可以加入自定义的加载器,来实现特殊的加载方式。举个例子,我们可以对class文件进行加密,加载时再利用自定义的类加载最其解密。
除了加载功能之外,类加载器还提供了命名空间的作用。在java虚拟机中,类的唯一性是由类加载器实例以及类的全名一同确定的。即便是通一串字节流,经由不同的类加载器加载,也会得到两个不同的类。在大型应用中,我们往往会借助这一特性,来运行同一个类的不同版本。
链接
链接是指将创建成的类合并至java虚拟机中,使之能执行的过程。它可以分为验证、准备及解析三个阶段。
验证:确保被加载的类能够满足java虚拟机的约束条件,检验被加载的类是否有正确的内部结构,并和其他类协调一致。
准备:为被加载类的静态字段分配内存,并设置默认初始值。
解析:将类中的二进制数据中的符号引用替换成直接引用(final修改的常量的替换)。
JVM并没有要你在链接过程中完成解析,它仅规定了:如果某些字节码使用了符号引用,那么在执行这些字节码之前,需要完成对这些符号引用的解析。
初始化
在java代码中如果要初始化一个静态字段,我们可以在声明时直接赋值,也可以在静态代码块中对其赋值。
如果直接赋值的静态字段被final修饰,并且他的类型是基本类型或字符串时,那么该字段便会被java编译器标记为常量值(ConstantValue),其初始化直接被java虚拟机完成。除此之外的直接赋值操作以及所有静态代码块中的代码,则会被java编译器置于同一方法中,并把它命名为<clinit>。
类加载的最后一步是初始化,便是为标记为常量值的字段赋值,以及执行<clinit>方法的过程。java虚拟机会通过加锁来确保类的<clinit>方法仅被执行一次。
只有当初始化完成之后,类才正式称为可执行的状态。
JVM初始化一个类分为几步:
1、假如这个类还没有被加载和链接,程序先加载并链接这个类。
2、假如该类的直接父类还没有被初始化,则先初始化其直接父类。
3、假如类中有初始化语句,则依次执行其初始化语句。
类的加载和初始化何时被触发
1、当虚拟机启动时,初始化用户指定的主类。(直接使用java.exe命令来运行某个主类)
2、创建类的实例(new方法)。
3、调用某个类的静态方法,初始化该静态方法所在的类。
4、访问某个类或接口的静态属性,初始化该静态属性所在的类。
5、使用反射机制来创建某个类或接口的对应java.lang.Class对象(Class.forName("Person")),初始化这个类。
6、子类的初始化会触发父类的初始化。
7、如果一个接口定义了default方法,那么直接实现或间接实现该接口的类的初始化,会触发该接口的初始化。
8、当初次使用MehodHandle实例时,初始化该MehodHandle指向的方法所在的类。
注:此文为极客时间郑雨迪专栏,java虚拟机讲解及自己查资料的学习总结。郑雨迪《深入拆解Java虚拟机》很不错。
java虚拟机类加载的更多相关文章
- Java虚拟机类加载机制——案例分析
转载: Java虚拟机类加载机制--案例分析 在<Java虚拟机类加载机制>一文中详细阐述了类加载的过程,并举了几个例子进行了简要分析,在文章的最后留了一个悬念给各位,这里来揭开这个悬 ...
- 深入理解Java虚拟机---类加载机制(简略版)
类加载机制 谈起类加载机制,在这里说个题外话,当初本人在学了两三个月的Java后,只了解了一些皮毛知识,就屁颠屁颠得去附近学校的招聘会去蹭蹭面试经验,和HR聊了一会后开始了技术面试,前抛出了两个简单的 ...
- 面试官,不要再问我“Java虚拟机类加载机制”了
关于Java虚拟机类加载机制往往有两方面的面试题:根据程序判断输出结果和讲讲虚拟机类加载机制的流程.其实这两类题本质上都是考察面试者对Java虚拟机类加载机制的了解. 面试题试水 现在有这样一道判断程 ...
- Java虚拟机类加载器及双亲委派机制
所谓的类加载器(Class Loader)就是加载Java类到Java虚拟机中的,前面<面试官,不要再问我"Java虚拟机类加载机制"了>中已经介绍了具体加载class ...
- [转]Java虚拟机类加载机制
原文地址:http://blog.csdn.net/u013256816/article/details/50829596 看到这个题目,很多人会觉得我写我的java代码,至于类,JVM爱怎么加载就怎 ...
- java虚拟机类加载机制和双亲委派模型
java虚拟机类加载机制:虚拟机把描述类的数据从class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的java类型. 类的生命周期是从类被加载到虚拟机内存中,到卸 ...
- 面试官,不要再问我“Java虚拟机类加载机制”了(转载)
关于Java虚拟机类加载机制往往有两方面的 面试题:根据程序判断输出结果和讲讲虚拟机类加载机制的流程.其实这两类题本质上都是考察面试者对Java虚拟机类加载机制的了解. 面试题试水 现在有这样一道判断 ...
- JVM(三)-java虚拟机类加载机制
概述: 上一篇文章,介绍了java虚拟机的运行时区域,Java虚拟机根据不同的分工,把内存划分为各个不同的区域.在java程序中,最小的运行单元一般都是创建一个对象,然后调用对象的某个 方法.通过上一 ...
- 【转载】Java虚拟机类加载机制与案例分析
出处:https://blog.csdn.net/u013256816/article/details/50829596 https://blog.csdn.net/u013256816/articl ...
- Java虚拟机类加载机制
看到这个题目,很多人会觉得我写我的java代码,至于类,JVM爱怎么加载就怎么加载,博主有很长一段时间也是这么认为的.随着编程经验的日积月累,越来越感觉到了解虚拟机相关要领的重要性.闲话不多说,老规矩 ...
随机推荐
- angularJS指令系统---Directive
指令:Directive angularJS 有一套完整的,可拓展的,用来帮助web应用开发的指令集: 在建立DOM期间,和HTML关联着的指令会被检测到,并被执行: 在angularJS中将前缀为 ...
- 170519、FastDFS分布式文件系统的安装与使用(单节点)
基于 于 D Do ubbo 的分布 式系统架构 视频 教程 高 级篇S FastDFS 分布 式 文件系统的安装与使用 (单 节点)跟踪 服务器 : 192.168.4.12 21 1 (edu- ...
- SaltStack生产案例-系统初始化
需求分析 一,系统初始化 1.1 关闭SELinux 1.2 关闭默认iptables 1.3 时间同步(配置NTP) 1.4 文件描述符(必备/etc/security/limmits.c ...
- Oracle表的维护(字段,重命名表名)
案例:银行里建的开卡信息 字段 字段类型 Id Number name Varchar2(64) sex Char2() birth Date money Number(10,2) 创建银行卡表 cr ...
- AngularJs:Directive指令用法
摘自:http://www.jb51.net/article/83051.htm 摘要:Directive(指令)是AngularJ非常强大而有有用的功能之一.它就相当于为我们写了公共的自定义DOM元 ...
- pandas 从txt读取DataFrame&DataFrame格式化保存到txt
前提 首先保证你txt里的文本内容是有规律可循的(例如,列与列之间通过“\t”.“,”等指定的可识别分隔符分隔): 例如我需要读取的数据,(\t)分隔: (此文件内容是直接以DataFrame格式化写 ...
- 迅雷7 纯净版v7.9.18.4724
http://soft2.xzstatic.com/2016/08/Thunder_7.9.13.4666_NoAD_VIP.exe http://www.downza.cn/soft/192064. ...
- 最长括号化长度 java
1:求最长括号, ()(()()( 例如,它的最长符合括号化的长度为4 package com.li.huawei; import java.util.Arrays; import java.util ...
- spark mllib和ml类里面的区别
mllib是老的api,里面的模型都是基于RDD的,模型使用的时候api也是有变化的(model这里是naiveBayes), (1:在模型训练的时候是naiveBayes.run(data: RDD ...
- PAT 1055 The World's Richest[排序][如何不超时]
1055 The World's Richest(25 分) Forbes magazine publishes every year its list of billionaires based o ...