首页 > 其他分享 >类加载的过程与触发时机

类加载的过程与触发时机

时间:2024-08-24 18:58:36浏览次数:5  
标签:触发 常量 初始化 虚拟机 引用 时机 class 加载

类加载过程

在这里插入图片描述

加载阶段

所谓加载,简而言之就是将 Java 类的字节码文件加载到机器内存中,一个Java文件从编码完成到最终执行,一般主要包括两个过程:编译和运行,其中编译就是把我们写好的java文件,通过javac命令编译成字节码,也就是我们常说的.class文件,编译过程中会对java代码做语法层面校验,有问题的话会编译失败并抛出编译期错误,然后运行则是把编译声称的.class文件交给Java虚拟机(JVM)执行。而我们所说的类加载过程即是指JVM虚拟机把.class文件中类信息加载进内存,并进行解析生成对应的class对象的过程。并在内存中构建出 Java 类的原型——类模板对象。所谓类模板对象,即class对象,class对象的实例数据是存储在堆(Heap)中的,就像其他对象一样,然而,类的元数据比如则是存储在方法区(Method Area)中的。类的元数据主要有类名称、父类、接口、访问修饰符、字段、方法、构造函数、注解、常量池、静态变量

实际上java的每个类被编译成.class文件的时候,java虚拟机(jvm)会自动为这个类生成一个类对象,这个对象保存了这个类的所有信息(成员变量,方法,构造器等),以后这个类要想实例化(也就是创建类的实例或创建类的对象)那么都要以这个class对象为蓝图(或模版)来创建这个类的实例。例如

class<?> c = Class.forName(“com.pojo.User”); 

c就是User的类对象,而 User u=new User();这个u就是以c为模版创建的,其实就相当于u=c.newInstance();反射的机制即基于这一基础。如果 JVM 没有将 Java 类的声明信息存储起来,则 JVM 在运行期也无法反射

简单来说:加载指的是把class字节码文件从各个来源通过类加载器装载入内存中的过程,在堆中生成class实例对象和方法区元空间生成类的元数据,

链接

验证

文件格式验证
四个验证过程中,只有格式验证是建立在二进制字节流的基础上的。格式验证就是对文件是否是0xCAFEBABE开头、class文件版本等信息进行验证,确保其符合JVM虚拟机规范。

这一阶段具体可能包括下面这些验证点:

  • 是否以魔数0xCAFEBABE开头。
  • 主、次版本号是否在当前虚拟机处理范围之内。
  • 常量池的常量中是否有不被支持的常量类型(检查常量tag标志)。
  • 指向常量的各种索引值是否有指向不存在的常量或不符合类型的常量。
  • CONSTANT_Utf8_info型的常量中是否有不符合UTF8编码的数据。
  • Class文件中各个部分及文件本身是否有被删除的或附加的其他信息

元数据验证
编译器的检查主要是基于源代码层面的静态分析。在类加载过程的验证阶段,Java虚拟机(JVM)将进行进一步的验证,确保编译后的字节码在加载到JVM时不会对运行时环境造成危害。这个过程包括了对字节码的结构性检查、控制流和数据流分析,以及确保符号引用的正确性等。

这意味着,即使代码在编译时没有错误,它也可能在类加载时的验证阶段失败。例如,如果类文件被篡改或损坏,或者与当前运行环境不兼容(如使用了不支持的版本号),则类验证会失败,虽然这些问题在编译时可能不会被检测到。

编译器和JVM的验证步骤是两个独立但互补的过程

准备

为 static 静态变量分配空间,设置默认值,需要注意

  • static 变量分配空间和赋值是两个步骤,分配空间在准备阶段完成,赋值在初始化阶段完成
  • 如果 static 变量是 final 的基本类型和字符串常量,那么编译阶段值就确定了,赋值在准备阶段完成,果 static 变量是 final 的引用类型,那么赋值阶段依然是在初始化阶段

解析

解析阶段是Java虚拟机将常量池内的符号引用替换为直接引用的过程

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

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

符号引用与虚拟机实现的内存布局无关,直接引用是和虚拟机实现的内存布局直接相关的,同一个符号引用在不同虚拟机实例上翻译出来的直接引用一般不会相同。

如果有了直接引用,那引用的目标必定已经在虚拟机的内存中存在。

解析动作主要针对类或接口、字段、类方法、接口方法、方法类型、方法句柄和调用点限定符这7类符号引用进行

类初始化阶段

初始化阶段会执行<clinit>,这个方法是由编译器按代码书写顺序收集并合并类中所有的静态变量,静态代码块生成的,构造器的执行顺序也是严格按照类中静态方法与静态代码的编写顺序,主要是完成静态属性的赋值与静态方法的执行,在子类初始化前要保证该子类的父类已经被初始化

触发类加载的时机

类的主动使用与类的被动使用都会出发类加载,但只有类的主动使用才会触发类的初始化,类的被动使用不会触发类的初始化

类的主动使用

  • 创建类的实例,包括通过new创建、反射创建(Class.newInstance/Constructor.newInstance)、clone、反序列化
  • 反射调用,使用Java反射API加载类,例如(如Class.forName)来反射类的方法或字段时
  • 被指定在Java虚拟机启动过程中加载,例如带main方法的类
  • 调用类的静态变量或者调用类的静态方法,需要注意,如果调用的是类的静态常量(如static final String xxx),则是属于被动使用
  • 继承:当初始化一个类的时候,如果它有父类还未被加载和初始化,那么父类也会被加载并被初始化

类的被动使用

  • 调用类的静态常量:如static final String xxx
  • 定义类的引用数组
  • 使用子类引用父类的静态字段: 父类会被初始化,子类会被加载但不会被初始化。
  • 通过类字面常量获取Class对象引用:例如MyClass.class这样的引用不会触发类的初始化
  • 通过类加载器加载类:调用ClassLoader的loadClass方法, 类会被加载但不会被初始化

标签:触发,常量,初始化,虚拟机,引用,时机,class,加载
From: https://blog.csdn.net/wwwwwww31311/article/details/141380564

相关文章

  • 讨论TableLayoutPanel加载缓慢和闪烁问题解决方案
    WinForm加载多个自定义控件时,会出现很严重的闪烁问题,很卡,一块一块的加载(像打开网页时,网络很卡的那种感觉)简直没法忍受。在网上搜索了好久,网上大部分的方法是一下4种,但是都不能有效的解决问题。1、将DoubleBuffered设置true,用双缓存处理Form界面内容加载,可以提高页面显......
  • dlopen 加载使用了std::thread 的so 导致crash的问题分析
    c++11的的createimplement是在thread.cc中实现的,这意味着创建代码在libstdc++.so中,创建代码需要使用与平台有关的apigcc(g++isapartofgcc)的预期:没有调用的thread的代码,不会产生对pthread的依赖,更重要的,不同配置的gcc的线程模型是不同的,依赖库也不同(即不一定是pthrea......
  • 为什么通过clear_refs可以使进程触发缺页?
    平台ARM64Linux6.10作者[email protected]背景最近在学习Linux的缺页异常时突然奇想,在不进行内存换出的情况下,如何让进程再次触发缺页?基于对ARMv8的理解,它的MMU的页表项中有个AF位,当AF为0时,当访问到对应的虚拟页时,会触发缺页。如果AF位为0,当访问到对应的虚拟页时......
  • 一起单测引起的项目加载失败惨案
    一、前言最近在开发一个功能模块时,在功能自测阶段,通过使用单测测试功能的完整性,在测试单测联通性使用到静态方法测试时,发现单测报错,通过查阅解决方案发现需要对Javaassist包进行排包或者升版本处理。通过排包解决掉单测报错,在部署项目时发现频繁报bean注入失败问题,最终定位发现......
  • 动态类加载
    动态类加载代码块加载顺序这里的代码块主要指的是这四种静态代码块:static{}构造代码块:{}无参构造器:ClassName()有参构造器:ClassName(Stringname)我创建两个类Person.javapublicclassPerson{publicstaticintstaticVar;publicstaticintid;static{Syst......
  • IIS网站图片不能加载
    去掉<addname="misson"path="*"verb="*"modules="IsapiModule"scriptProcessor="C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll"resourceType="File"requireAccess="None&......
  • Idea2024最新版本Mavn加载问题
    Idea2024最新版本Mavn加载问题简述由于公司项目多,各个项目不一致版本,有的jdk1.8、有jdk11,最近由于工作安排,我将从转到其它项目里面。至此开启了,我的新老项目编译不通过之路。mavenclean项目错误并将加载巨慢java.lang.OutOfMemoryError:GCoverheadlimitexceeded尝试......
  • 【JVM-类加载器】
    在JVM中主要有以下几种类加载器:一、启动类加载器(BootstrapClassLoader)作用:负责加载JVM自身需要的核心类库,这些类库主要是Java安装目录下的jre/lib目录中的类。例如,加载Java的核心类库如java.lang包下的类,包括Object、String等。特点:由C/C++语言实现......
  • 【Vue】el-autocomplete禁用时仍会触发下拉的问题
    文章目录问题解决问题el-autocomplete禁用时,点击后仍会触发下拉,导致出现bug<el-autocompletev-model="modelValue":fetch-suggestions="queryAsync"class="autocomplete":disabled="isDis"@select="doSelect($event,item)&......
  • js面试题 图片懒加载!
    一、原理只加载可视区域内的图片,而那些还未滑动到可视区域的图片先不加载,直到用户滚动到这些资源即将可见的时候才进行加载。若一个页面有大量的图片资源,网页首次打开时,若同时加载完这些资源,需要消耗大量的时间,利用图片懒加载,先加载部分图片,既不会影响用户体验,又能大幅提升首......