我的编程空间,编程开发者的网络收藏夹
学习永远不晚

详细分析JVM类加载机制

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

详细分析JVM类加载机制

前言

        ladies and gentleman , 你们好? ,我是羡羡 , 这节我们进入jvm的学习 , 我们知道 , jvm是java虚拟机, java代码的执行与 jvm 息息相关, 接下来我们来依次介绍 , 首先这节先来介绍 jvm 中的类加载部分

1. jvm 的组成

jvm组成可分为这四个部分

1.类加载器(ClassLoader)

2.运行时数据区(Runtime Data Area)

3.执行引擎(ExecutionEngine)

4.本地库接口(Native Interface)

那么一个程序在 jvm 中的运行过程是怎样的呢? 

       java代码首先被编译成字节码文件(Class文件),  通过不同操作系统上的 jvm 来加载解释 , 这个过程首先需要类加载器加载class文件 , 然后进行字节码校验 , 校验结束通过后通过jvm解释器翻译成机器码交给操作系统执行

      程序在执行之前先要把 java 代码转换成字节码(class 文件),jvm 首先需要把字节码通一定的方式 类加载器(ClassLoader) 把文件加载到内存中的运行时数据区(Runtime DataArea) ,而字节码文件是 jvm 的一套指 令集规范,并不能直接交个底层操作系统去执行,因此需要特定的命令解析器 执行引擎(Execution Engine) 将字节码翻译成底层系统指令再交由 CPU 去执行,而这个过程中需要调用其他语言的接口 本地库接口(Native Interface) 来实现整个程序的功能,这就是这 4 个主要组成部分的职责与功能

jvm整体结构如下图

 可能说到这里 , 初学的同学会有点懵 , 不过不用担心, 上图中的各个组成部分后面都会一一解释

2. 类加载

       通过上面 jvm的运行过程可知 , 类加载就是读取 class文件的过程 , 这期间需要用到类加载器 , 类加载器只负责加载 , 至于如何执行 , 则由执行引擎决定

类加载 又分为以下几个模块

      类加载器加载class文件到 jvm中 , 被称为DNA元数据模板 , jvm通过模板来创建实例 , 类加载器在此过程相当于担任了快递员的角色

那么类加载的过程是怎样的呢 ?

可以看到 , 分为三个过程 : 加载, 链接 ,初始化 

1. 加载  

1. 通过类名(地址)获取此类的二进制字节流.

2. 将这个字节流所代表的静态存储结构转换为方法区(元空间)的运行时结构.

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

 顾名思义 , 加载就是把类中的信息加载进 jvm 中

2. 链接

 链接又分为 3 个过程 : 验证, 准备 ,解析

(1) . 验证

检验被加载的类是否有正确的内部结构,并和其他类协调一致

        验证文件格式是否一致: class 文件在文件开头有特定的文件标识(字节码文件都以 CA FE BA BE 标识开头);主,次版本号是否在当前 java 虚拟机接收范围内

       元数据验证:对字节码描述的信息进行语义分析,以保证其描述的信息符合java 语言规范的要求,例如这个类是否有父类;是否继承浏览不允许被继承的类(final 修饰的类)

验证过程主要是看是否符合java语言的规范

(2) . 准备

准备:准备阶段则负责为类的静态属性分配内存,并设置默认初始值(int为0)

此过程不包含用 final 修饰的 static 常量(静态常量),在编译时进行初始化.

//准备阶段值为0
public static int value = 123;
//准备阶段值为123
public static final int value = 123;

(3) .解析

    将类的二进制数据中的符号引用替换成直接引用(符号引用是 Class 文件的逻辑符号,直接引用指向的方法区中某一个地址)

      将符号引用替换成直接引用, 这句话怎么理解呢 ? 这里来举个例子

public void method1(){
    method2();
}

        在 方法1 中调用 方法2 , 我们这样来写代码的时候, 这就只是符号引用 , 而当这段程序被加载进 jvm解析的时候 符号引用就会变成直接引用, 也就是指明此处真正的引用地址

3. 初始化

 在谈类的初始化过程之前, 先来考虑 , 类什么时候会被初始化? 

1 )创建类的实例,也就是 new 一个对象

2)访问某个类或接口的静态变量,或者对该静态变量赋值

3)调用类的静态方法

4)反射(Class.forName(“”))

5)初始化一个类的子类(会首先初始化子类的父类)

       初始化类的过程也是为类中成员赋值的过程 , 在链接过程中的准备过程中被static修饰的变量是赋了默认值(int型为0), 而在初始化过程中才会赋予我们赋的值

       我们常说 , 用 static 修饰的变量, 方法 , 代码块是跟类直接打交道的 , 我们说加载类的时候, 使用static修饰的成员也会被加载 , 此过程也是在类的初始化中完成

那么在初始化过程中, 赋值顺序是怎样的呢?

      如果同时包含多个静态变量和静态代码块,则按照自上而下的顺序依次执行。 如果初始化一个类的时候,其父类尚未初始化,则优先初始化其父类。

      顺序是:父类 static –> 子类 static –> 父类构造方法- -> 子类构造方法

下面代码 num 的值变化

3. 类加载器

        从开发人员的角度上来讲, 类加载器可分为3类 : 引导类加载器(启动类加载器), 扩展类加载器 , 应用程序类加载器

引导类加载器(启动类加载器)

     这个类加载器使用 C/C++语言实现,嵌套在 JVM 内部.它用来加载 java 核心类库.     

     并不继承于java.lang.ClassLoader , 没有父加载器 , 负责加载扩展类加载器和应用程序类加载器 , 并为它们指定父类加载器

     ClassLoader 类,它是一个抽象类,其后所有的类加载器都继承自 ClassLoader (不包括启动类加载器)

      引导类加载器作为顶级的类加载器, 非java语言实现 , 所以和java中其他类加载器也不存在继承关系等

扩展类加载器

 Java 语言编写的,由sun.misc.Launcher$ExtClassLoader 实现. 派生于 ClassLoader 类.

          负责从 java.ext.dirs 系统属性所指定的目录中加载类库,或从 JDK 系统安装目录jre/lib/ext 子目录(扩展目录)下加载类库.如果用户创建的 jar 放在此目录下,也会自动由扩展类加载器加载

应用程序类加载器

     Java 语言编写的,由 sun.misc.Launcher$AppClassLoader 实现. 派生于 ClassLoader 类.      加载我们自己定义的类,用于加载用户类路径(classpath)上所有的类.      该类加载器是程序中默认的类加载器.

我们自己写的类是由应用程序类加载器加载的, 类加载器结构示例如下

//获取应用程序类加载器  sun.misc.Launcher$AppClassLoader@18b4aac2
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
System.out.println(classLoader);
//获得父类加载器 sun.misc.Launcher$ExtClassLoader@74a14482
System.out.println(classLoader.getParent());
//扩展类加载器上一级是引导类加载器,不是java实现,为null
System.out.println(classLoader.getParent().getParent());
//拿到String类的类加载器,结果为null
//可见,String类为引导类加载器加载
ClassLoader classLoader1 = String.class.getClassLoader();
System.out.println(classLoader1);

另外还有一种叫做用户自定义类加载器 , 例如 tomcat

4. 双亲委派机制

什么是双亲委派机制呢? 

       Java 虚拟机对 class 文件采用的是按需加载的方式,也就是说当需要该类时才会 将它的class 文件加载到内存中生成 class 对象.而且加载某个类的 class 文件 时,Java 虚拟机采用的是双亲委派模式,即把请求交由父类处理,它是一种任务委 派模式.

.

      就是说呢, 如果类加载器接收到了加载请求, 并不会去立即加载这个类, 而是把请求交给它的上一级加载器去加载 , 上一级没有则继续往上找 , 直到顶级的类加载器(引导类加载器)也无法加载时, 开始往下找 , 如果有一级加载成功则返回, 最终加载器都无法加载时, 就会抛出ClassNotFoundException异常

      那么为什么要这样去做呢? 试想, 我们自己创建一个java.lang.String类

package java.lang;
public class String {
    public String(){
        System.out.println("自己的String");
    }
}

建立一个测试类

public class TestString {
    public static void main(String[] args) {
        new String();
    }
}

        试想 , "自己的String" 这句话会被输出吗 ? 答案肯定是不会

        因为加载类的时候会先往上走, 此时走到了引导类加载器, 引导类加载器发现此类没有被加载,并且自己可以加载, 那么java.lang.String 就会被加载了, 此时就会直接返回 

        那么双亲委派机制出现的原因就显而易见了

      安全,可避免用户自己编写的类动态替换 Java 的核心类,如 java.lang.String , 避免全限定命名的类重复加载(使用了 findLoadClass()判断当前类是否已加载)

5. 类的主动/被动使用

      JVM 规定,每个类或者接口被首次主动使用时才对其进行初始化,有主动使用,自然就有被动使用.那么什么时候类被主动使用呢?

  • 通过new关键字被导致类的初始化,这是大家经常使用的初始化一个类的方式,他肯定会导致类的加载并且初始化
  • 访问类的静态变量,包括读取和更新
  • 访问类的静态方法
  • 对某个类进行反射操作,会导致类的初始化
  • 初始化子类会导致父类的的初始化
  • 执行该类的 main 函数

除了上面的几种主动使用其余就是被动使用了

     1.引用该类的静态常量,注意是常量,不会导致初始化,但是也有意外,这里的常量是指已经指定字面量的常量,对于那些需要一些计算才能得出结果的常量就会导致初始化,比如:

public final static int NUMBER = 5 ; //不会导致类初始化,被动使用 public final static int RANDOM = new Random().nextInt() ; //会导致类的初始化,主动使用

     2.构造某个类的数组时不会导致该类的初始化

Student[] students = new Student[10]

      主动使用和被动使用的区别在于类是否会被初始化.

结语

       到此关于 jvm 类加载这一章就说完了 , 感谢您的阅读 , 后续将会进行 jvm 中运行时数据区的讲解 , 感谢您的支持 ,谢谢 !!!

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

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

详细分析JVM类加载机制

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

JVM分析之类加载机制详解

JVM内部架构包含类加载器、内存区域、执行引擎等。日常开发中,我们编写的java文件被编译成class文件后,jvm会进行加载并运行使用类。本次将对JVM加载部分进行分析,便于大家了解并掌握加载机制
2022-11-13

JVM类加载机制分析

Java虚拟机将编译后的.class文件加载到内存中,进行校验、转换、解析和初始化,到最终的使用,这就是类的加载机制。

JAVA虚拟机(JVM)详细介绍(五)——类加载机制

上篇中我们讲解了Class文件,这篇我们说说虚拟机是如何加载这些Class文件的?Class文件中的信息进入到虚拟机后会发生什么变化?这就涉及到了类加载机制。类加载机制是把类的数据从Class文件加载到内存,并对数据进行校验,转换解析和初始化,最终形成可以被虚
JAVA虚拟机(JVM)详细介绍(五)——类加载机制
2015-12-28

JVM类加载机制及生命周期的详细介绍

这篇文章主要讲解了“JVM类加载机制及生命周期的详细介绍”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“JVM类加载机制及生命周期的详细介绍”吧!一.目标:1.什么是类的加载?2.类的生命周期
2023-06-02

JVM优化:JVM加载机制详解——类装载子系统

类的初始化阶段是类加载过程的最后一个步骤, 之前介绍的几个类加载的动作里, 除了在加载阶段用户应用程序 可以通过自定义类加载器的方式局部参与外, 其余动作都完全由Java虚拟机来主导控 制。
JVM加载机制2024-11-30

jvm类加载器,类加载机制是什么

这篇文章主要介绍“jvm类加载器,类加载机制是什么”,在日常操作中,相信很多人在jvm类加载器,类加载机制是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”jvm类加载器,类加载机制是什么”的疑惑有所帮助!
2023-06-16

java类加载机制详细介绍

文章转载自:http://www.pythonheidong.com/blog/article/1152/在许多Java面试中,我们经常会看到关于Java类加载机制的考察,例如下面这道题:class Grandpa{ static {
java类加载机制详细介绍
2019-02-20

Java 类加载机制详细介绍

一、类加载器  类加载器(ClassLoader),顾名思义,即加载类的东西。在我们使用一个类之前,JVM需要先将该类的字节码文件(.class文件)从磁盘、网络或其他来源加载到内存中,并对字节码进行解析生成对应的Class对象,这就是类加
2023-05-31

jvm类加载器,类加载机制详解,看这一篇就够了

今天我们来讲讲jvm里类加载的过程,我们写了那么多类,却不知道类的加载过程,岂不是很尴尬。

好程序员Java分享JVM类加载机制

JVM相关概念jdk
jdk(Java Development Kit)Java开发包,是Java开发人员用于编译和调试程序的一套程序的集合。jre
jre(Java Runtime Evironment)Java运行时环境,是
2023-06-02

聊一聊Java的JVM类加载机制

这篇文章主要介绍了聊一聊Java的JVM类加载机制,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
2023-05-16

JVM类加载场景的实例分析

JVM类加载场景的实例分析,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种
2023-06-16

说说 JVM 的类加载机制『非专业』

类是在运行期间第一次使用时动态加载的,而不是一次性加载所有类。因为如果一次性加载,那么会占用很多的内存。
JVM加载机制2024-12-03

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录