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爱怎么加载就怎么加载,博主有很长一段时间也是这么认为的.随着编程经验的日积月累,越来越感觉到了解虚拟机相关要领的重要性.闲话不多说,老规矩 ...
随机推荐
- kerberos认证协议分析
Kerberos认证协议分析 Kerberos认证协议流程 如上图: * 第一步:client和认证服务器(AS)通信完成认证过程,如果认证成功AS返回给client一个TGT(用来向TGS获取tic ...
- struts2的action如果返回null会怎样
action return nullresponse里直接写要返回的东西, 返回null,就是说视图不跳转到任何地方,当然就出现空白页面了.如果想出现页面就需要在struts.xml文件里面配置res ...
- java父类可以强制转化成子类吗?
转自:http://blog.csdn.net/ld422586546/article/details/9707997 Java中父类强制转换成子类的原则:父类型的引用指向的是哪个子类的实例,就能转换 ...
- 日志记录---log4j详解
Apache官方项目地址 通常的日志记录的缺点是会减慢程序的运行速度,如果用普通的System.out的话影响视觉效果,另外解耦度也不好,而log4j的设计则使得日志记录变得可靠快速和可拓展性好. l ...
- rman备份的其它特性
1.7.3.1并发: 主要用于提高备份的速度,可以分为手动并发或自动并发 手动并发:通过分配多个通道并将文件指定到特定的通道 RMAN> run { 2> allocate channe ...
- Spring容器装配Bean的三种方式
欢迎查看Java开发之上帝之眼系列教程,如果您正在为Java后端庞大的体系所困扰,如果您正在为各种繁出不穷的技术和各种框架所迷茫,那么本系列文章将带您窥探Java庞大的体系.本系列教程希望您能站在上帝 ...
- apache工作模式worker以及prefork的切换
apache比较常用的工作模式有worker以及prefork两种方式. 如果在编译时候不指定,系统默认的是prefork模式:如果需要换成worker模式,需要在编译的时候带上编译参数:--with ...
- MVC学习之HtmlHelper
1.为什么要使用HtmlHelper? 1.首先HtmlHelper是一个类型,MVC中的ViewPage<TModel>中的一个属性Html属性,这个属性的类型就是HtmlHelper& ...
- 沈阳网络赛K-Supreme Number【规律】
26.89% 1000ms 131072K A prime number (or a prime) is a natural number greater than 11 that cannot be ...
- ubuntu下安装meshlab
PPA 安装,打开终端,输入以下命令: sudo add-apt-repository ppa:zarquon42/meshlab sudo apt-get update sudo apt-get i ...