关于Java的类加载机制

1、概述

        类会在运行期间第一次使用时,被类加载器动态加载至JVM。JVM不会一次性加载所有类。因为如果一次性加载,会占用很多的内存。

2、类的生命周期

 

类的生命周期包括以下 7 个阶段:

  • 加载(Loading)
  • 验证(Verification)
  • 准备(Preparation)
  • 解析(Resolution)
  • 初始化(Initialization)
  • 使用(Using)
  • 卸载(Unloading)

2.1类的加载过程

包含:加载、验证、准备、解析和初始化 ,一共包括5 个阶段。

2.1.1加载

(1)加载过程

  1. 通过类的完全限定名称获取定义该类的二进制字节流
  2. 将该字节流表示的静态存储结构转换为Metaspace元空间区的运行时存储结构。
  3. 在内存中生成一个代表该类的 Class 对象,作为元空间区中该类各种数据的访问入口。

(2)二进制字节流获取方式

  • 从 ZIP 包读取,成为 JAR、EAR、WAR格式的基础。
  • 从网络中获取,最典型的应用是 Applet。
  • 运行时计算生成,例如动态代理技术,在 java.lang.reflect.Proxy 使用 ProxyGenerator.generateProxyClass 的代理类的二进制字节流。
  • 由其他文件或容器生成,例如由 JSP 文件生成对应的 Class 类。

2.1.2验证

确保 Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。

2.1.3准备

使用的是元空间区的内存,为类变量(被 static 修饰的变量)分配内存并设置初始值。

实例变量不会在这阶段分配内存,它会在对象实例化时,随着对象一起被分配在堆中。

注意:根据不用类型初始值不同,int初始值一般为 0 值。

例如:下面的类变量 value 被初始化为 0 而不是 123

public static int value = 100;

如果类变量是常量,那么它将初始化为表达式所定义的值而不是 0。

public static final int value = 123;

2.1.4解析 

 将常量池的符号引用替换为直接引用的过程。其中解析过程在某些情况下可以在初始化阶段之后再开始,这是为了支持 Java 的动态绑定。

2.1.5初始化

初始化阶段是虚拟机执行类构造器 <clinit>()方法的过程。准备阶段,类变量已赋过一次系统要求的初始值,而在初始化阶段,根据程序员通过程序制定的主观计划去初始化类变量和其它资源。

<clinit>()是由编译器自动收集类中所有类变量的赋值动作静态代码块中的语句合并产生的,编译器收集的顺序与源文件顺序一致。

所以,静态语句块只能访问定义在它之前的类变量,定义在它之后的类变量只能赋值,不能访问

public class Test {static {i = 0;                // 给变量赋值可以正常编译通过System.out.print(i);  // 这句编译器会提示“非法向前引用”}static int i = 1;
}

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

在接口中有类变量初始化的赋值操作,因此接口与类一样都会生成 <clinit>() 方法,但接口中不可以使用静态语句块。接口与类不同的是,执行接口的 <clinit>() 方法不需要先执行父接口的 <clinit>() 方法。只有当父接口中定义的变量使用时,父接口才会初始化。另外,接口的实现类在初始化时也一样不会执行接口的 <clinit>() 方法。

此外一个类的 <clinit>() 方法是线程安全的。多个线程同时初始化一个类,只会有一个线程执行这个类的 <clinit>() 方法,其它线程都会阻塞等待,直到活动线程执行 <clinit>() 方法完毕。

3、类加载的时机

3.1主动引用

虚拟机规范中并没有强制约束何时进行加载,但是严格规定了下列六种情况必须对类进行加载:

3.1.1遇到特殊指令时

演示需要类

class Prent{static int A = 23;static final int VALUE = 10;static {System.out.println("Prent被加载");}public static void dosth(){};
}
class Son extends Prent{static {System.out.println("Son被加载");}
}

(1)当 jvm 执行 new指令时会加载类。即:当程序创建一个类的实例对象

public class Demo01 {public static void main(String[] args) {// newPrent p = new Prent();
}

(2)当 jvm 执行 getstatic指令时会加载类。即:程序访问类的静态变量(不是静态常量,常量会被加载到运行时常量池)

// getstatic
System.out.println(Prent.A);

(3)当 jvm 执行 putstatic指令时会加载类。即:程序给类的静态变量赋值。

        // putstaticPrent.A = 188;

(4) 当 jvm 执行 invokestatic指令时会加载类。即:程序调用类的静态方法。

// invokestaticPrent.dosth();

 3.1.2反射

使用 java.lang.reflect包的方法对类进行反射调用时如 Class.forname("..."), 或newInstance() 等等。如果类没初始化,需要触发类的加载。

3.1.3继承

加载一个类,如果其父类还未加载,则先触发该父类的加载。

3.1.4main方法所在类

当虚拟机启动时,用户需要定义一个要执行的主类 ,虚拟机先加载这个类。

3.1.5接口实现

当一个接口中定义了 JDK8 新加入的默认方法(被 default 关键字修饰的接口方法)时,如果有这个接口的实现类发生了加载,则该接口要在实现类之前被加载

3.2被动引用

除主动引用之外,所有引用类的方式都不会触发加载,称为被动引用

(1)通过子类引用父类的静态字段,不会导致子类加载。

System.out.println(Son.A);

(2)数组类型

通过数组定义来引用类,不会触发此类的加载。该过程会对数组类进行加载,数组类是一个由虚拟机自动生成的、直接继承自 Object 的子类,其中包含了数组的属性和方法。

//array继承自object与Prent无继承关系
Prent[] array = new Prent[10];

(3)类中常量

常量在编译阶段会存入调用类的常量池中,本质上并没有直接引用到定义常量的类

System.out.println(Prent.VALUE);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/106502.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【uni-app】

准备工作&#xff08;Hbuilder&#xff09; 1.下载hbuilder&#xff0c;插件使用Vue3的uni-app项目 2.需要安装编译器 3.下载微信开发者工具 4.点击运行->微信开发者工具 5.打开微信开发者工具的服务端口 效果图 准备工作&#xff08;VScode&#xff09; 插件 uni-cr…

Codeforces Round 827 (Div. 4) D 1e5+双重for循环技巧

Codeforces Round 827 (Div. 4) D 做题链接&#xff1a;Codeforces Round 827 (Div. 4) 给定一个由 n个正整数 a1,a2,…,an&#xff08;1≤ai≤1000&#xff09;组成的数组。求ij的最大值&#xff0c;使得ai和aj共质&#xff0c;否则−1&#xff0c;如果不存在这样的i&#…

5.9.Webrtc线程事件处理

在前面的课程中呢&#xff0c;我已经向你介绍了事件处理的一些基础知识&#xff0c;那今天呢&#xff0c;我们再来看一下外边儿rtc下事件处理的基本逻辑是什么&#xff1f; 那首先呢&#xff0c;我们来看一下事件是如何协调线程工作的&#xff0c;那就如果这张图所展示的有两个…

直播进入新风口:XR虚拟直播市场火爆,未来发展势不可挡

&#xfeff; 近年来&#xff0c;直播行业随着技术的不断发展&#xff0c;呈现出了蓬勃的发展态势。在这个竞争日益激烈的直播行业中&#xff0c;XR虚拟直播成为了最新的风口。XR虚拟直播是一种新型的直播形式&#xff0c;通过虚拟现实技术&#xff0c;让用户置身于直播现场&a…

【HELLO NEW WORLD】一封来自开放自动化时代的邀请函

​ 施耐德电气开放自动化平台&#xff0c;迈向开放、高效与韧性、可持续、以人为本的未来工业。 HELLO WORLD 是人类在信息世界开启的第一行 也是我们走进自动化领域迎来的第一句问候 如今 面临向数字化与自动化加速转型的新变局 工业领域迫切地需要一场变革 走向更加高效…

ClickHouse进阶(十三):Clickhouse数据字典-3-文件数据源及Mysql数据源

进入正文前&#xff0c;感谢宝子们订阅专题、点赞、评论、收藏&#xff01;关注IT贫道&#xff0c;获取高质量博客内容&#xff01; &#x1f3e1;个人主页&#xff1a;含各种IT体系技术,IT贫道_大数据OLAP体系技术栈,Apache Doris,Kerberos安全认证-CSDN博客 &#x1f4cc;订阅…

【洛谷算法题】P5704-字母转换【入门1顺序结构】

&#x1f468;‍&#x1f4bb;博客主页&#xff1a;花无缺 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 花无缺 原创 收录于专栏 【洛谷算法题】 文章目录 【洛谷算法题】P5704-字母转换【入门1顺序结构】&#x1f30f;题目描述&#x1f30f;输入格式&a…

入门人工智能 ——自然语言处理介绍,并使用 Python 进行文本情感分析(5)

入门人工智能 ——自然语言处理介绍&#xff0c;并使用 Python 进行文本情感分析&#xff08;5&#xff09;&#xff09; 入门人工智能 ——自然语言处理介绍&#xff0c;并使用 Python 进行文本情感分析介绍自然语言处理的挑战NLP的基本任务NLP的基本技术NLP的应用领域 使用 P…

2023数模国赛C 题 蔬菜类商品的自动定价与补货决策-完整版创新多思路详解(含代码)

题目简评&#xff1a;看下来C题是三道题目里简单一些的&#xff0c;考察的点比较综合&#xff0c;偏数据分析。涉及预测模型和运筹优化(线性规划)&#xff0c;还设了一问开放型问题&#xff0c;适合新手入门&#xff0c;发挥空间大。 题目分析与思路&#xff1a; 背景&#x…

数据库服务器是什么意思?数据库服务器有哪些?

数据库服务器是什么意思?现在市场上有很多的服务器的类型&#xff0c;比如数据库服务器&#xff0c;但是很多人对数据库服务器是什么意思?数据库服务器有哪些并不是很熟悉&#xff0c;那么&#xff0c;聚名企服为您详解一下。 一&#xff1a;数据库服务器是什么意思 数据库服…

想要精通算法和SQL的成长之路 - 相交链表

想要精通算法和SQL的成长之路 - 相交链表 前言一. 相交链表&#xff08;双指针&#xff09; 前言 想要精通算法和SQL的成长之路 - 系列导航 一. 相交链表&#xff08;双指针&#xff09; 原题链接 思路如下&#xff1a; 1.我们假设 headA链表的长度为 a。headB链表的长度为b…

多线程之基础篇(一)

一、Thread类 1、线程的创建 大家都熟知创建单个线程的三种方式&#xff0c;通过继承Thread类创建线程并重写该类的run()方法&#xff1b;通过实现Runnable接口创建线程一样要重写run()方法&#xff1b;以上的两个run()方法都是线程的执行体&#xff1b;第三&#xff0c;使用…