【Java 】Java 类加载和类加载器

news/2024/11/17 10:59:35/

文章目录

  • 前言
  • 一、加载
  • 二、链接
    • 验证
    • 准备
    • 解析
  • 三、初始化
    • 发生的时机
    • 不会触发类的初始化
  • 四、类加载器
    • 双亲委派模式

前言

Java 的类加载阶段分为:加载、链接、初始化,而链接的过程中包括:验证、准备、解析。

一、加载

将类的字节码载入方法区中,内部采用 C++ 的 instanceKclass 描述 Java 类

instanceKclass 的重要字段:

  • _java_mirror:Java 类镜像,存放类对象的地址,例如对于 String,存放的就是String.class
  • _super:即父类
  • _methods:即方法
  • _constants:即常量池
  • _class_loader:类加载器
  • _vtable:虚方法表
  • _itable:接口方法表

在这里插入图片描述

二、链接

链接阶段包括验证、准备、初始化三个部分

验证

验证类是否符合 JVM 规范,进行安全性检查,例如:检查 Java 文件的魔数

准备

为 static 变量分配地址空间,设置默认值

  • static 变量分配空间和赋值是两个步骤,分配空间是在准备阶段完成,而赋值是在初始化阶段完成;
  • 若 static 变量是 final 类型的,且变量类型为基本数据类型或者字符串对象,则在准备阶段进行赋值;
  • 若 static 变量是 final 类型的,且变量类型为引用对象,则仍在初始化阶段进行赋值;

解析

将常量池中的符号引用解析为直接引用

三、初始化

初始化调用 ()v,即执行类的构造方法,代码块等,虚拟机会保证这个类的线程安全

发生的时机

概括的说,类的初始化是懒惰的

  • main 方法所在的类,总会被首先初始化;
  • 首次访问类的静态变量或者静态方法,因为这些变量不是 final 的,会在类的初始化阶段进行赋值;
  • 子类初始化,会引起父类的初始化;
  • 子类方法父类的静态变量,会导致父类的初始化;
  • Class.forName;
  • new 会导致初始化;

不会触发类的初始化

  • 访问类的 static final 静态变量(基本类型和字符串),不会被初始化,因为这些变量的赋值是在准备阶段;
  • 类对象.class 不会触发类的初始化;
  • 创建该类的数组不会触发初始化;
  • 类加载器的 loadClass 方法;
  • Class.forName 的参数 2 为 false 时

四、类加载器

以 JDK8 为例

名称加载哪里的类说明
Bootstrap ClassLoaderJAVA_HOME/jre/lib无法直接访问
Extension ClassLoaderJAVA_HOME/jre/lib/ext上级为 Bootstrap ClassLoader,访问为 null
Application ClassLoaderclasspath上级为 Extension ClassLoader
自定义类加载器自定义上级为 Application ClassLoader

类加载器的作用:加载类的二进制字节码

双亲委派模式

双亲委派模式是一种Java类加载机制,它定义了一种层次化的父子关系,由父类加载器向下委派请求,直到找到合适的类加载器为止。

  • 首先会检查缓存,查找该加载器是否已经加载过这个类了,如果没有就去父类的加载器中去寻找;
  • 如果缓存中没有找到,就会自顶而下用的类加载器去创建该类;
  • 最终返回该类即可;
protected Class<?> loadClass(String name, boolean resolve)throws ClassNotFoundException{synchronized (getClassLoadingLock(name)) {// First, check if the class has already been loaded// 检查缓存,是否已经加载过这个类Class<?> c = findLoadedClass(name);if (c == null) {long t0 = System.nanoTime();try {if (parent != null) {// 向上级的累加器中找c = parent.loadClass(name, false);} else {// 向 Bootstrap 类加载器中找c = findBootstrapClassOrNull(name);}} catch (ClassNotFoundException e) {// ClassNotFoundException thrown if class not found// from the non-null parent class loader}// 如果缓存没有找到,就去创建if (c == null) {// If still not found, then invoke findClass in order// to find the class.long t1 = System.nanoTime();// 调用 findClass 去创建类c = findClass(name);// this is the defining class loader; record the statssun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);sun.misc.PerfCounter.getFindClasses().increment();}}if (resolve) {resolveClass(c);}return c;}}

http://www.ppmy.cn/news/53182.html

相关文章

二维码在设备点维一体化管理中的应用

随着科技发展&#xff0c;设备点维一体化管理体系应运而生&#xff0c;该管理体系的出现让设备维护保养变得更加高效精细化。 设备点维一体化管理体系以设备点检和维护保养为基础&#xff0c;通过日常、专业及精密点检&#xff0c;对点检测得的数据和设备给油脂保养情况进行统…

关于容器(Docker)的形象比喻

1 将容器比喻为样板间 容器是一种特殊的进程 容器依赖与Linux操作系统内核的几项技术&#xff1a;namespace、cgroup、chroot namespace 与编程语言里的 namespace 有点类似&#xff0c;它可以创建出独立的文件系统、主机名、进程号、网络等资源空间&#xff0c;相当于给进程…

记录-有意思的气泡 Loading 效果

这里给大家分享我在网上总结出来的一些知识&#xff0c;希望对大家有所帮助 今日&#xff0c;群友提问&#xff0c;如何实现这么一个 Loading 效果&#xff1a; 这个确实有点意思&#xff0c;但是这是 CSS 能够完成的&#xff1f; 没错&#xff0c;这个效果中的核心气泡效果&am…

【机智云物联网低功耗转接板】+模拟无线远程控制仪表启停

GE211 是机智云自研的定制化的物联网转接板&#xff0c;使用 ESP32-C3-WROOM-02 通讯模块&#xff0c;适用于白色智能家电等设备应用。硬件设计上采用支持 WiFi 和 BLE 的双模无线通信模块&#xff0c;具备TTL电平转换串口&#xff0c;免开发快速接入&#xff0c;提高开发效率。…

前端开发之vue动态路由实现方案

前端开发之vue动态路由实现方案 前言2. 实现1、登录页面创建登录函数和watch监听路由2、调用的login方法&#xff08;1&#xff09;登录方法&#xff08;2&#xff09;存储token 3、router.push的时候调用路由守卫&#xff08;1&#xff09;创建路由守卫&#xff0c;建议路由守…

docker以外挂目录的方式部署springboot项目

前置准备&#xff1a; 清单&#xff1a; 安装有docker的Linuxspringboot打包的jar文件&#xff08;该项目只有一个返回"hello world"接口&#xff09; Linux的IP地址&#xff1a;192.168.221.129 springboot项目的接口&#xff1a; 1、上传jar文件至Linux 我上传…

Java有很多初学者常见的问题

作为一门流行的编程语言&#xff0c;Java有很多初学者常见的问题。以下是两个例子&#xff1a; 1.理解Java的数据类型 Java有不同的数据类型&#xff0c;包括整型、浮点型、布尔型等等。初学者可能会困惑如何选择合适的数据类型来存储他们的数据。例如&#xff0c;他们可能会…

thinkphp 的 whereIN() 、where IN 如何使用?

在 ThinkPHP 中&#xff0c;可以通过 whereIN 方法来构建 WHERE IN 子句。以下是 whereIN 方法的语法&#xff1a; $result Db::table(table_name)->whereIn(column, $array)->select();table_name&#xff1a;表示表名&#xff1b;column&#xff1a;表示要查询的列名…