jvm类的加载机制_java类加载流程及原理

jvm类的加载机制_java类加载流程及原理1.类加载器的组织结构转载请注明出处:http://blog.csdn.net/seu_calvin/article/details/52301541类加载器ClassLoader是具有层次结构的,也就是父子关系。其中,Bootstrap是所有类加载器的父亲。(1)Bootstrapclassloader:启动类加载器当运行Java虚拟机时,这个类加载器被创建,…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

1. 类加载器的组织结构

转载请注明出处:JVM——Java类加载机制总结_SEU_Calvin的博客-CSDN博客

类加载器 ClassLoader是具有层次结构的,也就是父子关系。其中,Bootstrap是所有类加载器的父亲

(1)Bootstrapclass loader 启动类加载器

当运行Java虚拟机时,这个类加载器被创建,它负责加载虚拟机的核心类库,如java.lang.*等。

(2)Extensionclass loader:标准扩展类加载器

用于加载除了基本 API之外的一些拓展类

(3)AppClassLoader加载应用程序和程序员自定义的类

运行下面的程序,结果也显示出来了:

jvm类的加载机制_java类加载流程及原理

从运行结果可以看出加载器之间的父子关系,ExtClassLoader的父Loader返回了null

原因是BootstrapLoader(启动类加载器)是用C语言实现的,找不到一个确定的返回父Loader的方式。

2. 类的加载机制

类被加载到虚拟机内存包括加载、链接、初始化几个阶段。其中链接又细化分为验证、准备、解析。

这里需要注意的是,解析阶段在某些情况下可以在初始化阶段之后再开始,这是为了支持Java的运行时绑定。各个阶段的作用整理如下:

 

2.1 加载阶段

加载阶段可以使用系统提供的类加载器(ClassLoader)来完成,也可以由用户自定义的类加载器完成,开发人员可以通过定义类加载器去控制字节流的获取方式

1通过类的全名产生对应类的二进制数据流

2)将这些二进制数据流转换为方法区的运行时数据结构

3)创建代表这个类的java.lang.Class对象。作为方法区这些数据的访问入口

 

2.2 链接阶段(实现 Java 的动态性的重要一步)

1验证:验证阶段的主要目的是确保class文件字节流的正确性,要验证比如class文件格式规范、这个类是否继承了final类、不能把一个父类对象赋值给子类数据类型等等。

2准备:准备阶段为方法区中的静态变量分配内存空间。并将其赋值为初始值,所有原始类型的值都为0。如float0f int0boolean0、引用类型为null

3解析:解析阶段把符号引用解析为直接引用

符号引用是一个字符串,它唯一标识一个类、一个字段、一个方法等目标。

而直接引用对于类变量、类方法指的是指向方法区的指针,然后对于实例方法、实例对象来说就是偏移量,比如一个实例方法,子类中方法表中的偏移量和父类是一致的,这个偏移量可以确定某个方法的位置。

 

2.3 初始化

到了初始化阶段,才是真正执行用户定义程序代码。在初始化阶段就是执行类构造器方法的过程,工作包括赋值类变量、静态语句块的合并

//定义在静态语句块之后的变量可以赋值,但不能访问
public class Test{
    static{
        i=0;//給变量赋值,可以通过编译
        System.out.print(i);//这句编译器会提示非法向前引用
    }
    static int i=1;
}

初始化过程会被触发的条件汇总:

1)使用new关键字实例化对象、访问一个类的静态字段静态方法的时候。

2对类进行反射调用的时候。

3)当初始化子类时,如果发现其父类还没有进行过初始化,则进行父类的初始化

 

【关于构造器方法拓展知识】(可以不看)

1)类构造器<clinit>()方法与类的构造函数不同,它不需要显式调用父类构造,虚拟机会保证在子类<clinit>()方法执行之前,父类的<clinit>()方法已经执行完毕。因此在虚拟机中的第一个执行的<clinit>()方法的类肯定是java.lang.Object

2)由于父类的<clinit>()方法先执行,也就意味着父类中定义的静态语句块要优先于子类的变量赋值操作。

3<clinit>()方法不是必须的,如果一个类中没有静态语句,那么编译器可以不为这个类生成<clinit>()方法。

4接口中不能使用静态语句块,和类不同的是,执行接口的<clinit>()方法不需要先执行父接口<clinit>()方法。只有当父接口中定义的变量被使用时,父接口才会被初始化。另外,接口的实现类在初始化时也一样不会执行接口的<clinit>()方法。

5)虚拟机会保证一个类的<clinit>()方法在多线程环境中被正确加锁和同步,可能会导致阻塞。

3. 类加载的三种方式

1)由 new 关键字创建一个类的实例。

2)调用 Class.forName() 方法,通过反射加载类。

3)调用某个ClassLoader实例的loadClass()方法。

 

三者的区别汇总如下:

1)方法12都是使用的当前类加载器。方法3是用户指定的类加载器加载

2)方法1是静态加载,23是动态加载。

3)对于两种动态加载,如果程序需要类被初始化,就必须使用Class.forName(name)的方式

Class.forName(className);
//实际上是调用的是:
Class.forName(className, true, this.getClass().getClassLoader());//第二个参为true即默认类需要初始化,初始化会触发目标对象静态块的执行和静态变量的初始化
ClassLoader.loadClass(className);
//实际上调用的是:
ClassLoader.loadClass(name, false);//第二个参数即默认得到的class还没有进行链接,意味着不进行初始化等系列操作,即静态代码块不会执行

jvm类的加载机制_java类加载流程及原理

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/169728.html原文链接:https://javaforall.net

(0)
上一篇 2022年8月11日 上午7:46
下一篇 2022年8月11日 上午8:00


相关推荐

  • DOS分区的分析

    DOS分区的分析转自 http blog csdn net liuying 1001 article details Microsoft 将使用 DOS 分区体系的磁盘称为 主引导记录 MasterBootRe MBR 很多人都认为 DOS 分区 就是指 Windows 下的分区 我原先也是这么认为的 其实 DOS 分区并不是以操作系统而划分的分区体系 而是指使用 主引导记录 MBR 的

    2026年3月20日
    2
  • django的drf框架的优点_一个类要具有可序列化

    django的drf框架的优点_一个类要具有可序列化前言上一篇文章我们讲述了序列化,这篇就带大家一起来实现以下序列化Serializer我们使用序列化类Serializer,我们来看下源码结构,这里推荐使用pycharm左边导航栏的Structu

    2022年7月31日
    9
  • 以太坊 如何挖矿_以太坊asic矿机

    以太坊 如何挖矿_以太坊asic矿机以太坊(ETH)是什么?它是公链之王,有人说它可能会超越比特币(BTC),其应用非常广泛,在以太坊世界里挖矿可以得到奖励,那么怎么挖矿?一下是以太坊的挖矿教程,相信看完教程后,你也能迅速的开始自己的挖矿之旅!我来详细道来。开始挖矿前的准备工作:1、硬件需求:系统要求.Windows7/8/10系统—–显卡要求.AMD或NVIDIA显卡,至少拥有4GB显存。2、软件准备:首先需要一款挖矿软件。Claymore’sDualMiner是原版挖矿软件需要掌握基础知识才可以使

    2022年10月15日
    8
  • 奔图 Pantum P3502DN 打印机驱动

    奔图 Pantum P3502DN 打印机驱动奔图 PantumP3502D 打印机驱动是官方提供的一款打印机驱动 本站收集提供高速下载 用于解决打印机与电脑连接不了 无法正常使用的问题 本动适用于 WindowsXP Windows7 Windows8 Windows1032 64 位操作系统 有需要的朋友可以来本站下载安装 奔图 PantumP3502D 打印机驱动 http www equdong net qudong bt Pantum 7874 html

    2026年3月26日
    1
  • numpy 中的randn()函数介绍「建议收藏」

    numpy 中的randn()函数介绍「建议收藏」>>>np.random.randn()2.1923875335537315#random生成正态分布矩阵:Forrandomsamplesfrom,use:sigma*

    2022年8月6日
    8
  • 什么是字节码指令?[通俗易懂]

    什么是字节码指令?[通俗易懂]字节码指令简介: Java虚拟机的指令由一个字节长度的、代表着某种特定含义的数字(称为操作码,Opcode)以及跟随其后的零至多个代表此操作所需参数(称为操作数,Operands)而构成。由于Java虚拟机采用面向操作数栈而不是寄存器的架构,所以大多数的指令都不包含操作数,只有一个操作码。由于限制了Java虚拟机操作码的长度为一个字节,所以指令集的操作码总数不可能超过256条。字节码与数据…

    2022年10月7日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号