摘要:虚拟机有个一加载机制,叫做双亲委派模型。扩展类加载器扩展类加载器的父类的加载器是启动类加载器。验证验证的目的就是需要符合虚拟机的规范。虚拟机会通过加锁的方式确保方法只执行一次。
引言
上一篇文章谈到Java运行的流程,其中有一环是类加载。今天就继续深入探讨JVM如何加载虚拟机。
首先JVM加载类的一般流程分三步:
·加载
·链接
·初始化
那么是否全部Java类都是这样三步走的方式加载呢?我们可以从Java的数据类型去出发。Java分基本类型和引用类型。其中按照面向对象的特性,一切皆对象,那么对于基本类型也应该是对象。但是为了在执行效率和内存占用上进行调优,Java将基本类型特殊处理。所以Java基本类型加载都是Java虚拟机预先定义好了,所以没有加载这个步骤了。引用类型就是类,接口,数组。其中数组是直接由虚拟机直接生成的。类和接口是字节流,都是需要加载。
首先先看下基本类型的默认值和值域。
总结
1.无符号类型:boolean和char
2.boolean在Java虚拟机中,根据虚拟机规范转换为int类型,false为0,true为1
引用类型中的数组是直接由Java虚拟机直接生成,接下来直接讲类和接口。为了叙述方便直接统称为类。类的加载分三步。
加载加载是通过加载器进行加载的。Java虚拟机有个一加载机制,叫做双亲委派模型。具体就是当一个类加载器拿到这个类的时候先给自己的父类加载器进行加载,如果父类加载器没有找到所请求的类,才会给该类加载器。还是挺尊老爱幼的。那么加载器有很多中,在Java9之前分三类。Java9之后分两类。
分类:
Java9之前
·启动类加载器:负责加载最为基础和最为重要的类。比如存放在jre的lib目录的jar包中的类以及虚拟机参数-Xbootclasspath指定的类。
·扩展类加载器:扩展类加载器的父类的加载器是启动类加载器。扩展类加载器加载相对次要但是又通用的类。比如jre中lib/ext目录下的jar包中的类以及由系统变量java.ext.dir指定的类。
·应用类加载器:应用类加载器的父类加载器是扩展类加载器。负责加载应用加载应用程序路径的类(这里的应用程序的路径就是虚拟机参数-cp/-classpath,系统变量java.class.path或环境变量CLASSPATH指定的路径)。
Java9之后
启动类加载器:同上
平台类加载器:Java9引入模块系统,所以除了少数的几个关键模块是用启动类加载器加载,其余的都有平台类加载器加载。
类加载器除了提供加载功能,还提供命名空间的功能,这个就很像Java的包名一样。即时是同一个类,经过不同的类加载器,命名不同那这两个类也是不是同一个类。
链接何为链接,就是讲加载的类合并至Java虚拟机,使之能够执行的过程。具体流程可以分类验证,准备以及解析三个过程。
验证:验证的目的就是需要符合Java虚拟机的规范。
准备:为加载类的静态字段分配内存,部分Java虚拟机还会在这阶段构造其他跟类层次相关的数据结构,比如说用来实现虚方法的动态绑定的方法表。
解析:当class文件加载到虚拟机之前这个类不知道自己的成员变量和成员方法的地址,所以编译器会生成一个符号引用,这个符号应用包括所在类的名字,目标方法的名字,接收参数类型以及返回类型。解析就是将这个符号引用转化为实际引用。如果符号引用指向的类没有加载,那么会触发这个类进行加载,但是不会链接和初始化。
Java虚拟机规范并没有要求链接过程完成解析,如果某些字节码使用了符号引用,那么在执行这些字节码之前,需要完成解析。
初始化初始化就是初始化静态字段,如果静态字段被final修改,那么该字段就会被标记为常量值,其初始化直接由Java虚拟机完成。其他的初始化静态字段的代码Java编译器会放在一个方法中并且命名为
初始化就是为常量值直接赋值和执行
那么什么时候会触发初始化:
1.当虚拟机启动,初始化用户指定的类。
2.当遇到用以新建目标类实例的new指令时,初始化new指令的目标类。
3.当遇到调用静态方法的指令时,初始化该静态方法所在的类。
4.但遇到访问静态字段的指令时,初始化该静态字段所在的类。
5.子类的初始化会触发父类的初始化。
6.如果接口定义了default方法,那么直接实现或者间接实现该接口的类的初始化,会触发该接口的初始化。
7.使用反射API对某个类进行反射调用时,会初始化该类。
8.当初次调用MethodHandle实例时,初始化该MethodHandle指向的方法所在的类。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/73524.html
摘要:实现这个口号的就是可以运行在不同平台上的虚拟机和与平台无关的字节码。类加载过程加载加载是类加载的第一个阶段,虚拟机要完成以下三个过程通过类的全限定名获取定义此类的二进制字节流。验证目的是确保文件字节流信息符合虚拟机的要求。 引言 我们知道java代码编译后生成的是字节码,那虚拟机是如何加载这些class字节码文件的呢?加载之后又是如何进行方法调用的呢? 一 类文件结构 无关性基石 ja...
摘要:验证验证是连接阶段的第一步,这一阶段的目的是为了确保文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。字节码验证通过数据流和控制流分析,确定程序语义是合法的符合逻辑的。 看过这篇文章,大厂面试你「双亲委派模型」,硬气的说一句,你怕啥? 读该文章姿势 打开手头的 IDE,按照文章内容及思路进行代码跟踪与思考 手头没有 IDE,先收藏,回头看 (万一哪次面试问...
摘要:验证验证阶段的主要目的是为了确保文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。不同的虚拟机对类验证的实现可能会有所不同,但大致都会完成以下四个阶段的验证文件格式的验证元数据的验证字节码验证和符号引用验证。 原文地址 虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验,转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,Thisis ...
阅读 3195·2021-09-06 15:02
阅读 2242·2019-08-30 15:48
阅读 3437·2019-08-29 11:08
阅读 3280·2019-08-26 13:55
阅读 2438·2019-08-26 13:35
阅读 3160·2019-08-26 12:11
阅读 2596·2019-08-26 11:48
阅读 879·2019-08-26 11:42