返回顶部
首页 > 资讯 > 后端开发 > Python >Java JVM类加载机制解读
  • 206
分享到

Java JVM类加载机制解读

2024-04-02 19:04:59 206人浏览 八月长安

Python 官方文档:入门教程 => 点击学习

摘要

目录1.什么是类加载2.类加载的过程2.1加载2.2验证2.3准备2.4解析2.5初始化【重中之重之重中重】第一段代码:第二段代码:第三段代码:最后一段代码:总结1.什么是类加载 首

1.什么是类加载

首先你要知道一个类的从被加载到虚拟机内存中开始,到被初始化为止,是为类加载的整个过程。下图就是类加载的整个过程:

在这里插入图片描述

一个类只有经历了加载、验证、准备、解析、初始化这五个关卡才能被认为是实现了类加载。这,就是类加载。

注意一点:上面五个过程并不是按部就班地“完成”,而是按部就班地“执行”(除解析过程外)。执行时一定是先开始加载,再开始验证,但加载过程中也可能会直接开始验证。

2.类加载的过程

2.1加载

“加载”只是是“类加载”过程的第一个阶段,关于在什么时候开始,规范并没有进行强制约束,可以让虚拟机自行把握。在这个阶段中,Java虚拟机需要完成以下三件事:

1)通过一个类的全限定名来获取这个类的二进制字节流

2)将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构

3)在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的方问入口

可以用一句话概括:加载是一个读取Class文件,将其转化为某种静态数据结构存储在方法区内,并在堆中生成一个便于用户调用的java.lang.Class类型的对象的过程

2.2验证

验证是连接阶段的第一步,这个阶段的目的是确保Class文件的字节流中包含的信息符合约束要求,,保证这些信息被当做代码运行后不会危害虚拟机自身的安全

这一过程了解即可。

2.3准备

准备阶段是正式为类中定义的变量(这里说的是静态变量,也就是被static修饰的变量)分配内存,并设置类变量初始值的阶段。

这里有两点需要强调:

1)首先这里进行内存分配的仅仅是类变量,而不包括实例变量,实例变量将会在对象实例化时随着对象一起分配在Java堆中。

2)其次这里设置的初始值“通常情况”下是数据的零值,而不是用户本身对它赋的初值。

如下代码:


public static int a = 10;

变量a在准备阶段后的初始值是0,而不是10,因为现在只是在类加载过程中,还没有执行任何方法。

上面说到“通常情况”,那就说明还有特殊情况咯,加修饰词final时:


public static final int a = 10;

这时在准备阶段虚拟机就会将a设置为10。其实也不难理解:我们将它设置为常量,那就肯定在任何时候都不能修改啊,天子犯法与庶民同罪!

2.4解析

解析阶段是Java虚拟机将常量池内的符号引用替换为直接引用的过程,这一过程也可能在初始化后进行,并不一定和流程图的执行顺序一样。

符号引用:符号引用以一组符号来描述所引用的目标,符号可以是任何形式的字面量,只要使用时能无歧义地定位到目标即可。

直接引用:直接引用是可以直接指向目标的指针、相对偏移量或者是一个能间接定位到目标的句柄。

这一过程比较复杂,有兴趣可以参考《深入理解Java虚拟机》

2.5初始化【重中之重之重中重】

类的初始化阶段是类加载过程的最后一个阶段。在这个阶段Java虚拟机才开始真正执行类中编写的Java程序代码。

初始化阶段有以下六种情况必须立即对类进行“初始化”:

  • 1)使用new关键字实例化对象的时候
  • 2)读取或设置一个类的静态字段(被final修饰、已在编译期把结果放入常量池的静态字段除外)的时候
  • 3)调用一个类的静态方法的时候
  • 4)使用java.lang.reflect包的方法对类进行反射调用的时候,如果类没有进行过初始化,则需要先触发其初始化。
  • 5)当初始化一个类的时候,如果发现其父类还没有进行过初始化,则需要先触发其父类的初始化。
  • 6)当虚拟机启动时,用户需要指定一个要执行的主类(包含main()方法的那个类),虚拟机会先初始化这个主类。

光说不行,主要看

第一段代码:


package com.bit.JVMTest;

class Father {

    public  static int a = 10;
    
    static {
        System.out.println("爸爸静态代码块");
    }
}


class Son extends Father{

    public static int b = 20;
    
    static {
        System.out.println("儿子静态代码块");
    }
}


public class ClassLoaderTest {
    public static void main(String[] args) {
        System.out.println(Son.b);
    }
}

运行结果:
爸爸静态代码块
儿子静态代码块
20

首先Son.b是在读取Son类自己的静态字段,这点符合上面六中情况的第二种:读取或设置一个类的静态字段(被final修饰、已在编译期把结果放入常量池的静态字段除外)的时候需要进行初始化。

其次Son类继承Father类,也就符合第五条:当初始化一个类的时候,如果发现其父类还没有进行过初始化,则需要先触发其父类的初始化,所以我们先初始化的应该是Father类,然后是Son类。

因此,打印的内容首先是爸爸静态代码块(父类先初始化),然后是儿子静态代码块(子类再初始化),最后是我们想要打印的b(20)本身。

再看

第二段代码:


package com.bit.JVMTest;

class  grandFather{
    static{
        System.out.println("爷爷静态代码块");
    }
}

class Father extends grandFather{

    public  static int a = 10;
    
    static {
        System.out.println("爸爸静态代码块");
    }
}


class Son extends Father{

    public static int b = 20;
    
    static {
        System.out.println("儿子静态代码块");
    }
}


public class ClassLoaderTest {
    public static void main(String[] args) {
        System.out.println(Son.a);
    }
}

运行结果:
爷爷静态代码块
爸爸静态代码块
10

首先要明确:Son.a是在读取父类Father类的静态字段(注意a字段在Son类的父类中),而不是读取Son类本身的静态字段

因此这次不会初始化Son类本身。

因此这次不会初始化Son类本身。

因此这次不会初始化Son类本身。

其它的和第一段代码很相似:JVM在初始化Father类的时候,发现这个类还有一个父类没有被初始化,那就先初始化它的父类:grandFather

因此,打印的内容首先是爷爷静态代码块(Father类的父类先初始化),然后是爸爸静态代码块(Father类再初始化),最后是我们想要打印的a(10)本身。

第三段代码:


package com.bit.JVMTest;

class  grandFather{
    static{
        System.out.println("爷爷静态代码块");
    }
}

class Father extends grandFather{

    public final static int a = 10;
    
    static {
        System.out.println("爸爸静态代码块");
    }
}


class Son extends Father{

    public static int b = 20;
    
    static {
        System.out.println("儿子静态代码块");
    }
}


public class ClassLoaderTest {
    public static void main(String[] args) {
        System.out.println(Son.a);
    }
}

运行结果:10

看到这里是不是想说卧**你*个*。

别急别急,这里的主函数调用虽然和第二段代码一样,但是注意!!!我们给a这个静态字段加了一个final修饰符

再看六条中的第(2)条:读取或设置一个类的静态字段(被final修饰、已在编译期把结果放入常量池的静态字段除外)的时候会触发类加载。

也就是说我们读取的a是被final修饰的,读取这种静态字段并不会引起任何类的初始化,所以就直接打印a(10)了。

再看

最后一段代码:


package com.bit.JVMTest;


class Father {

   public Father(){
       System.out.println("爸爸构造方法");
   }

    static {
        System.out.println("爸爸静态代码块");
    }

    {
        System.out.println("爸爸普通代码块");
    }
}

class Son extends Father{
    public Son(){
        System.out.println("儿子构造方法");
    }

    static {
        System.out.println("儿子静态代码块");
    }

    {
        System.out.println("儿子普通代码块");
    }
}

public class ClassLoaderTest extends Son{
    public static void main(String[] args) {
        System.out.println("开始");
        new Son();//这里实例化一个Son类的对象
        System.out.println("结束");
    }
}

运行结果:
 爸爸静态代码块
 儿子静态代码块
 开始
 爸爸普通代码块
 爸爸构造方法
 儿子普通代码块
 儿子构造方法
 结束

看到这里是不是欲哭无泪,我**不学了我。别急先听我细细分析一波~
这里有一个细节:主类继承了Son类!,这貌似没什么啊,但是还有一个细节:我们的main()方法是主类中的静态方法!看到这里是不是明白了些什么?

没错!当我们调用main()方法的时候,就引起了主类的初始化,主类继承Son类,Son类继承Father类,所以就先进行Father类的初始化:打印爸爸静态代码块,接着Son类初始化:打印儿子静态代码块,最后该终于我主类初始化了:代码中没什么可以初始化的…(尴尬)。

接下来是第二阶段:执行main()方法:

1.先打印:开始字样。

2.接着是构造 Son()实例,那么就会先构造它的父类Father()的实例:构造实例时按照先执行代码块,再执行构造方法的顺序来。所以就先打印了:爸爸普通代码块、爸爸构造方法 这几个大字。然后再执行构造Son()的实例,构造顺序一样,所以就后打印了:儿子普通代码块、儿子构造方法 这几个大字。

3.最后打印:结束字样。

此时main()才方法真正结束。

总结

我们平常所说的类加载体现在代码上就是初始化这一阶段,我这里结束的也仅限于此,想了解详细的类加载可以参考《深入理解Java虚拟机》这本书,也可以看其他博主的知识总结。感谢你能看到这里!

到此这篇关于Java JVM类加载机制解读的文章就介绍到这了,更多相关Java JVM 类加载机制内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: Java JVM类加载机制解读

本文链接: https://lsjlt.com/news/157530.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Java JVM类加载机制解读
    目录1.什么是类加载2.类加载的过程2.1加载2.2验证2.3准备2.4解析2.5初始化【重中之重之重中重】第一段代码:第二段代码:第三段代码:最后一段代码:总结1.什么是类加载 首...
    99+
    2024-04-02
  • jvm虚拟机类加载机制详解
    目录1 概述2 类的加载时机3 类的加载过程3.1 加载3.2 验证3.3 准备3.4 解析3.5 初始化4 类加载器4.1 双亲委派模型4.2 破坏双亲委派模型1 概述 ​ Jav...
    99+
    2024-04-02
  • 聊一聊Java的JVM类加载机制
    目录加载(Loading)连接(Linking)初始化(Initialization)类初始化的时机总结Java虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验、转换...
    99+
    2023-05-16
    Java JVM JVM类加载机制
  • jvm类加载器,类加载机制是什么
    这篇文章主要介绍“jvm类加载器,类加载机制是什么”,在日常操作中,相信很多人在jvm类加载器,类加载机制是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”jvm类加载器,类加载机制是什么”的疑惑有所帮助!...
    99+
    2023-06-16
  • JVM分析之类加载机制详解
    目录1、前言2、类加载是什么3、类加载过程3.1 加载3.2 链接3.3 初始化4、总结1、前言 JVM内部架构包含类加载器、内存区域、执行引擎等。日常开发中,我们编写的java文件...
    99+
    2022-11-13
    JVM类加载机制 JVM类加载
  • 好程序员Java分享JVM类加载机制
    JVM相关概念jdk<br>jdk(Java Development Kit)Java开发包,是Java开发人员用于编译和调试程序的一套程序的集合。jre<br>jre(Java Runtime Evironment...
    99+
    2023-06-02
  • 详细分析JVM类加载机制
    目录前言1. jvm 的组成2. 类加载1. 加载  2. 链接3. 初始化3. 类加载器引导类加载器(启动类加载器)扩展类加载器应用程序类加载器4. 双亲委派机...
    99+
    2024-04-02
  • jvm类加载机制怎么实现
    JVM类加载机制是通过类加载器来实现的。类加载器负责在JVM运行时将字节码文件加载到内存中,并将其转换为可执行的类。类加载器主要分为...
    99+
    2024-04-02
  • JAVA虚拟机(JVM)详细介绍(五)——类加载机制
    上篇中我们讲解了Class文件,这篇我们说说虚拟机是如何加载这些Class文件的?Class文件中的信息进入到虚拟机后会发生什么变化?这就涉及到了类加载机制。类加载机制是把类的数据从Class文件加载到内存,并对数据进行校验,转换解析和初始...
    99+
    2015-12-28
    java教程 JVM
  • Java虚拟机JVM类加载机制(从类文件到虚拟机)
    目录一、类加载机制简介二、类加载机制过程 2.1、加载(Load)2.2、连接(Linking)2.3、初始化(Initialize)三、类加载器Classloader&n...
    99+
    2024-04-02
  • java虚拟机JVM类加载机制原理(面试必问)
    目录1、类加载的过程。1)加载2)验证3)准备4)解析5)初始化2、Java 虚拟机中有哪些类加载器?1)启动类加载器(Bootstrap ClassLoader):2)扩展类加载器...
    99+
    2024-04-02
  • Java的类加载机制
    很长一段时间里,我对 Java 的类加载机制都非常的抗拒,因为我觉得太难理解了。但为了成为一名优秀的 Java 工程师,我决定硬着头皮研究一下。01、字节码在聊 Java 类加载机制之前,需要先了解一下 Java 字节码,因为它和类加载机制...
    99+
    2018-10-24
    java教程 Java
  • JVM【类加载与GC垃圾回收机制】
    JVM【类加载与GC垃圾回收机制】 🍎一.JVM🍒1.1JVM简介🍒1.2JVM执行流程 🍎二.JVM运行时数据区...
    99+
    2023-09-06
    jvm java 开发语言
  • 面试必时必问的JVM 类加载机制详解
    目录前言正文1、类加载的过程。1)加载2)验证3)准备4)解析5)初始化2、Java 虚拟机中有哪些类加载器?1)启动类加载器(Bootstrap ClassLoader):2)扩展...
    99+
    2024-04-02
  • Java之类加载机制案例讲解
    1.类加载 <1>.父子类执行的顺序 1.父类的静态变量和静态代码块(书写顺序) 2.子类的静态变量和静态代码块(书写顺序) 3.父类的实例代码块(书写顺序) 4.父类...
    99+
    2024-04-02
  • 如何处理JVM类加载机制及类缓存问题
    这篇文章给大家分享的是有关如何处理JVM类加载机制及类缓存问题的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。前言大家应该都知道,当一个Java项目启动的时候,JVM会找到main方法,根据对象之间的调用来对cla...
    99+
    2023-05-30
  • 一文详解Java中的类加载机制
    目录一、前言二、类加载的时机2.1 类加载过程2.2 什么时候类初始化2.3 被动引用不会初始化三、类加载的过程3.1 加载3.2 验证3.3 准备3.4 解析3.5 初始化四、父类...
    99+
    2024-04-02
  • Java中类加载机制的实例讲解
    这篇文章主要介绍“Java中类加载机制的实例讲解”,在日常操作中,相信很多人在Java中类加载机制的实例讲解问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java中类加载机制的实例讲解”的疑惑有所帮助!接下来...
    99+
    2023-06-20
  • JVM类加载机制过程以及原理是什么
    这篇文章主要介绍“JVM类加载机制过程以及原理是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“JVM类加载机制过程以及原理是什么”文章能帮助大家解决问题。一、做一个小测试通过注释,标注出下面两个...
    99+
    2023-07-05
  • 如何深入理解Java虚拟机JVM类加载初始化
    如何深入理解Java虚拟机JVM类加载初始化,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。 Classloader的作用,概括来说就是将编译后的class装载、...
    99+
    2023-06-17
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作