虚拟机(JVM)如何加载类

首先JVM加载类的一般流程分三步:

  • 加载
  • 链接
  • 初始化

那么是否全部Java类都是这样三步走的方式加载呢?我们可以从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的包名一样。即时是同一个类,经过不同的类加载器,命名不同那这两个类也是不是同一个类。

(ps:

** 启动类加载器:由java虚拟机直接生成,是由C++语言实现的,用null来代替。主要加载:D:\work_soft\java\jre\lib中.jar包中的类以及虚拟机参   数-Xbootclasspath指定的类。

** 扩展类加载器:其父类加载器为启动类加载器。主要加载D:\work_soft\java\jre\lib\ext中.jar的类

** 应用类加载器:其父类加载器为扩展类加载器。主要加载应用程序路径下的类

** 自定义类加载器:其父类加载器为应用类加载器。

)

链接

何为链接,就是讲加载的类合并至Java虚拟机,使之能够执行的过程。具体流程可以分类验证,准备以及解析三个过程。

验证:验证的目的就是需要符合Java虚拟机的规范。

准备:为加载类的静态字段分配内存,部分Java虚拟机还会在这阶段构造其他跟类层次相关的数据结构,比如说用来实现虚方法的动态绑定的方法表。

解析:当class文件加载到虚拟机之前这个类不知道自己的成员变量和成员方法的地址,所以编译器会生成一个符号引用,这个符号应用包括所在类的名字,目标方法的名字,接收参数类型以及返回类型。解析就是将这个符号引用转化为实际引用。如果符号引用指向的类没有加载,那么会触发这个类进行加载,但是不会链接和初始化。

Java虚拟机规范并没有要求链接过程完成解析,如果某些字节码使用了符号引用,那么在执行这些字节码之前,需要完成解析。

初始化

初始化就是初始化静态字段,如果静态字段被final修改,那么该字段就会被标记为常量值,其初始化直接由Java虚拟机完成。其他的初始化静态字段的代码Java编译器会放在一个方法中并且命名为.

初始化就是为常量值直接赋值和执行方法的过程。Java虚拟机会通过加锁的方式确保方法只执行一次。

那么什么时候会触发初始化:

1.当虚拟机启动,初始化用户指定的类。

2.当遇到用以新建目标类实例的new指令时,初始化new指令的目标类。

3.当遇到调用静态方法的指令时,初始化该静态方法所在的类。

4.但遇到访问静态字段的指令时,初始化该静态字段所在的类。

5.子类的初始化会触发父类的初始化。

6.如果接口定义了default方法,那么直接实现或者间接实现该接口的类的初始化,会触发该接口的初始化。

7.使用反射API对某个类进行反射调用时,会初始化该类。

8.当初次调用MethodHandle实例时,初始化该MethodHandle指向的方法所在的类。

原文地址:https://www.cnblogs.com/mark5/p/11063605.html

时间: 2024-10-08 00:58:15

虚拟机(JVM)如何加载类的相关文章

JVM加载类的过程,双亲委派机制中的方法

JVM加载类的过程: 1)JVM中类的整个生命周期: 加载=>验证=>准备=>解析=>初始化=>使用=>卸载  1.1.加载 类的加载阶段,主要是获取定义此类的二进制字节流,并将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构,最后在Java堆中生成一个代表这个类的java.lang.Class对象作为方法区这些数据的访问入口.相对于类加载过程的其他阶段,加载阶段是开发期可控性最强的阶段.我们可以通过定制不通的类加载器,也就是ClassLoader来控制二进制

java中JVM加载类的时机

一.描述 java中的类在什么时候被JVM虚拟机加载呢?因为静态成员初始化的时候会在类首次加载的时候执行, 我们通过测试一个静态代码块的执行时间来判断JVM加载该类的时间. 总结:JVM只在需要某个类或者使用Class.forName(className)强制加载类的时候才会被调用,如果只是声明某个类的引用,而没有创建对象则不会加载该类. 二.源代码 1.只是声明某个类的引用,而没有创建对象则JVM不会加载该类 package tong.yue.day4_25; /** * java中的类在什么

03 Java 虚拟机是如何加载 Java 类的

Java 引用类型 Java 中的引用类型细分为四种:类,接口,数组类和泛型参数. 因为泛型参数会在编译过程中被擦除,所以 Java 虚拟机实际上只有前三种.数组类是由 Java 虚拟机直接生成的,其他两种则有对应的字节流. 无论是数组类还是其他两种类型,Java 虚拟机都需要对其进行链接和初始化. 加载 加载就是查找字节流,然后据此创建类的过程.数组类由 Java 虚拟机直接生成,其他类则需要 Java 虚拟机借助类加载器来完成查找字节流的过程. 类加载器有很多种,除了启动类加载器以外,其他的

jvm加载类的过程

前言: 说下这篇文章的来龙去脉:昨天接到了阿里小哥哥的面试电话,小哥哥问我jvm加载类的过程.然后我巴拉巴拉说了一堆classLoader装载类的过程.然后小哥哥说我不是要问这些...好吧装载加载傻傻分不清楚. jvm加载类过程(本人不会,以下内容由小哥哥解释给我听的): classLoader装载类 连接(包括验证,准备,解析:小哥哥详述了这三个步骤..因为我比较疑问哈哈哈) 初始化 (小哥哥开始问我这个具体初始化过程) ( 本人其实脑子一片浆糊,很多概念傻傻分不清除)比如:类的初始化和对象的

《深入理解Java虚拟机》- Java虚拟机是如何加载Java类的?

Java虚拟机是如何加载Java类的?  这个问题也就是面试常问到的Java类加载机制.在年初面试百战之后,菜鸟喜鹊也是能把这流程倒背如流啊!但是,也只是字面上的背诵,根本就是像上学时背书考试一样. tonight ! 我们把它映射到实战里,看看如何用代码说明这个流程. ready! go!  ----------------在这之前还是搞点理论吧,不然又要先去百度加载机制流程了. 一.类加载机制(理论部分) 类加载机制有三大过程:加载.链接.初始化.其中链接又细分为验证.准备及解析. Java

jvm加载类

作为jvm的用户,从使用者角度来看,我们给jvm输入一个class文件,得到了一个Class对象.我们可以猜想下jvm加载类的过程:class文件有规定的格式,jvm去解析class文件流,读magic, major version, minor version等值(最简单的举例),然后生成Klass对象,并放到一个map中. 首先有个全局的认识,jvm把已加载的类放在一个hashtable中.class SystemDictionary : AllStatic {    // Hashtabl

Android运行时ART加载类和方法的过程分析

在前一篇文章中,我们通过分析OAT文件的加载过程,认识了OAT文件的格式,其中包含了原始的DEX文件.既然ART运行时执行的都是翻译DEX字节码后得到的本地机器指令了,为什么还需要在OAT文件中包含DEX文件,并且将它加载到内存去呢?这是因为ART运行时提供了Java虚拟机接口,而要实现Java虚拟机接口不得不依赖于DEX文件.本文就通过分析ART运行时加载类及其方法的过程来理解DEX文件的作用. 老罗的新浪微博:http://weibo.com/shengyangluo,欢迎关注! 在前面An

URLClassLoader动态加载类

说明: Java利用ClassLoader将类载入内存,并且在同一应用中,可以有很多个ClassLoader,通过委派机制,把装载的任务传递给上级的装载器的,依次类推,直到启动类装载器(没有上级类装载器).如果启动类装载器能够装载这个类,那么它会首先装载.如果不能,则往下传递.当父类为null时,JVM内置的类(称为:bootstrap class loader)就会充当父类.想想眼下的越来越多用XML文件做配置文件或者是描述符.部署符.其实这些通过XML文档描述的配置信息最终都要变成Java类

java反射并不是什么高深技术,面向对象语言都有这个功能,而且功能也很简单,就是利用jvm动态加载时生成的class对象

java反射并不是什么高深技术,面向对象语言都有这个功能. 面向对象语言都有这个功能,而且功能也很简单,就是利用jvm动态加载时生成的class对象,去获取类相关的信息 2.利用java反射可以调用类的私有方法么?private()方法 答:可以,class取出method,method继承executable类,executable类继承AccessibleObject类,AccessibleObject有个setAccessiable()设置这个方法是否可访问. 则设置成true,就可将pr