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虚拟机类加载的更多相关文章

  1. Java虚拟机类加载机制——案例分析

    转载: Java虚拟机类加载机制--案例分析   在<Java虚拟机类加载机制>一文中详细阐述了类加载的过程,并举了几个例子进行了简要分析,在文章的最后留了一个悬念给各位,这里来揭开这个悬 ...

  2. 深入理解Java虚拟机---类加载机制(简略版)

    类加载机制 谈起类加载机制,在这里说个题外话,当初本人在学了两三个月的Java后,只了解了一些皮毛知识,就屁颠屁颠得去附近学校的招聘会去蹭蹭面试经验,和HR聊了一会后开始了技术面试,前抛出了两个简单的 ...

  3. 面试官,不要再问我“Java虚拟机类加载机制”了

    关于Java虚拟机类加载机制往往有两方面的面试题:根据程序判断输出结果和讲讲虚拟机类加载机制的流程.其实这两类题本质上都是考察面试者对Java虚拟机类加载机制的了解. 面试题试水 现在有这样一道判断程 ...

  4. Java虚拟机类加载器及双亲委派机制

    所谓的类加载器(Class Loader)就是加载Java类到Java虚拟机中的,前面<面试官,不要再问我"Java虚拟机类加载机制"了>中已经介绍了具体加载class ...

  5. [转]Java虚拟机类加载机制

    原文地址:http://blog.csdn.net/u013256816/article/details/50829596 看到这个题目,很多人会觉得我写我的java代码,至于类,JVM爱怎么加载就怎 ...

  6. java虚拟机类加载机制和双亲委派模型

    java虚拟机类加载机制:虚拟机把描述类的数据从class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的java类型. 类的生命周期是从类被加载到虚拟机内存中,到卸 ...

  7. 面试官,不要再问我“Java虚拟机类加载机制”了(转载)

    关于Java虚拟机类加载机制往往有两方面的 面试题:根据程序判断输出结果和讲讲虚拟机类加载机制的流程.其实这两类题本质上都是考察面试者对Java虚拟机类加载机制的了解. 面试题试水 现在有这样一道判断 ...

  8. JVM(三)-java虚拟机类加载机制

    概述: 上一篇文章,介绍了java虚拟机的运行时区域,Java虚拟机根据不同的分工,把内存划分为各个不同的区域.在java程序中,最小的运行单元一般都是创建一个对象,然后调用对象的某个 方法.通过上一 ...

  9. 【转载】Java虚拟机类加载机制与案例分析

    出处:https://blog.csdn.net/u013256816/article/details/50829596 https://blog.csdn.net/u013256816/articl ...

  10. Java虚拟机类加载机制

    看到这个题目,很多人会觉得我写我的java代码,至于类,JVM爱怎么加载就怎么加载,博主有很长一段时间也是这么认为的.随着编程经验的日积月累,越来越感觉到了解虚拟机相关要领的重要性.闲话不多说,老规矩 ...

随机推荐

  1. getOwnPropertyNames() & keys()

    1.getOwnPropertyNames方法可以获得对象的所有属性名,并储存于一个数组当中. keys方法只能获取可遍历的属性名并储存于数组. 2.在完成notepad模块模拟的过程中使用了getO ...

  2. CSS Spritec下载,精灵图,雪碧图,初探之原理、使用

    CSS Spritec下载,精灵图,雪碧图,初探之原理.使用 关于CSS Sprite CSSSprites在国内很多人叫css精灵雪碧图,是一种网页图片应用处理方式.它允许你将一个页面涉及到的所有零 ...

  3. Codeforces Round #434 (Div. 2, based on Technocup 2018 Elimination Round 1)

    A. k-rounding 题目意思:给两个数n和m,现在让你输出一个数ans,ans是n倍数且末尾要有m个0; 题目思路:我们知道一个数末尾0的个数和其质因数中2的数量和5的数量的最小值有关系,所以 ...

  4. 使用google字体发生http://fonts.gstatic.com/s/ubuntu/v8/_aijTyevf54tkVDLy-dlnFtXRa8TVwTICgirnJhmVJw.woff2

    我在使用adminTLE后台模板时,有时候会有 http://fonts.gstatic.com/s/ubuntu/v8/_aijTyevf54tkVDLy-dlnFtXRa8TVwTICgirnJh ...

  5. 如何打造高性能Web应用

    Sean Hull是Heavyweight Internet Group的创始人兼高级顾问,拥有20年以上技术顾问相关经验,曾为多家知名机构提供咨询,其中包括The Hollywood Reporte ...

  6. MVC项目,bootstrap升级后index.d.ts编译出错

    安装最新的Typescript组件 下载链接 https://www.microsoft.com/en-us/download/details.aspx?id=48593

  7. 解决SpringMVC中文乱码

    第一种:表单提交后controller获得中文参数后乱码解决方案 注意: 1: form表单提交方式为必须为post,get方式下面spring编码过滤器不起效果 2: jsp页面编码设置为UTF-8 ...

  8. 小米范工具系列之六:小米范 web查找器2.x版本发布

    小米范web查找器是一款快速识别端口及服务的小工具. 此工具使用java 1.8以上版本运行. 下载地址:http://pan.baidu.com/s/1c1NDSVe  文件名web finder ...

  9. ansible(3)

    一.setup模块 ansible的setup模块主要用来收集信息,查看参数: [root@localhost ~]# ansible-doc -s setup # 查看参数,部分参数如下: filt ...

  10. Mirror--镜像用户同步

    --=========================================--在镜像搭建后,在主库服务器上创建登录,并在数据库上建立对应用户,--数据库中用户被同步到镜像数据库中,但登录是 ...