面试官:Java 类加载过程是怎么样的?又被问麻了。。

简介: 面试官:Java 类加载过程是怎么样的?又被问麻了。。

来源:blog.csdn.net/hsz2568952354/article/details/96763284


最近在看Java虚拟机,正好看到类加载这块,所以简单记录下所学到的知识,作为笔记。


首先,我们编写好的Java代码,经过编译变成.class文件,然后类加载器把.class字节码文件加载到JVM中,接着执行我们的代码,最后将类卸载出JVM。而从类加载到虚拟机到卸载出虚拟机的这一整个生命周期总共可以分为7个步骤,分别为加载、验证、准备、解析、初始化、使用和卸载,其中验证、准备和解析又称为连接阶段。接下来简单介绍下各个阶段是干嘛的。


加载是“类加载”的第一个阶段,就是将需要用到的类对应的.class字节码文件加载到虚拟机内存,并在方法区中生成一个java.lang.Class对象,作为程序访问这个类的各种数据的访问入口。


public class Test {

   public static void main(String[] args) {

       User user = new User();

   }

}



看一下上面这段代码,经过编译会生成两个字节码文件Test.class和User.class,接着会将包含main方法的这个类加载到虚拟机内存中开始执行,当执行到User user = new User(),发现需要用到User类,就会将User.class加载到内存中。所以简单的说,当需要用到哪个类时,就回去加载哪个类,Java的自带的核心类会在虚拟机启动时就会加载,包括包含main方法的启动类。但其实,类加载也挺复杂的,只是我了解的也不深,目前就理解成这样吧,后面再深入研究。


第二阶段验证,从字面上就可以看出这个阶段是来校验加载进来的.class文件中的内容是否符合规范,毕竟编译成.class文件后还是可以人为的对这个文件进行修改,那如果改的乱七八糟,压根不符合虚拟机的规范,那虚拟机就没法执行了,所以说这一步还是比较关键的。至于如何验证,还没有研究。


准备阶段我引用《深入理解Java虚拟机》中的一句话:准备阶段是正式为类变量分配内存并设置类变量初始值的阶段,这些变量所使用的内存都将在方法区中进行分配。这也比较好理解,看下面一段代码:


public class Test {

   public static int value = 10;

}

1

2

当需要用到这个类时,会先将这个类加载到内存中,并验证字节码文件的合法性。验证通过后就会进行准备工作了,会为这个类中的类变量分配内存空间,就是上面的value变量,并给一个初始值。


注意,仅包括类变量,不包括实例变量和局部变量等,并且只是给一个初始值,int型的初始值是0,所以准备过后,value的值是0,而不是10,而真正赋值为10是在初始化阶段。我还在其它资料上看到,这一阶段也会给这个类分配内存空间,先给类分配内存,在给它里面的类变量分配内存。


解析阶段是将常量池中的符号引用替换为直接引用的过程,这一部分内容我还没搞懂,所以这里就不过多记录了,简单了解一下。


初始化阶段是类加载中核心的一步了,还是以上面的代码为例,准备阶段我们已经为value变量分配了内存空间并给了初始值,现在就是真正给value赋值的时候,把10赋给了value。如果类中还含有静态代码块,也会在这一阶段执行。这里还要一点要注意,初始化类的时候,如果父类还没加载和初始化,也会触发父类的加载和初始化。


使用就没什么好说了,初始化完就可以开始使用这个对象了。


卸载是类的生命周期中的最后一阶段,即将方法区中无用的类回收,而类需要同时满足下面3个条件才算无用的类:


该类所有的实例都已经被回收,也就是Java堆中不存在该类的任何实例。

加载该类的ClassLoader已经被回收。

该类对应的java.lang.Class对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。

同时满足上述3个条件的类即可回收,但不一定就会回收,可通过参数配置。


下面用一张图来简单展示类的加载流程:


image.png


以上就是Java类的加载过程,当然,只是简单的说明了一下,刚接触,还是有很多地方不清楚,先大概有一个这样的印象,后面再慢慢深入理解。


参考资料:


《深入理解Java虚拟机》

《从0开始带你成为JVM实战高手》

————————————————


相关文章
|
6天前
|
Java
课时14:Java数据类型划分(初见String类)
课时14介绍Java数据类型,重点初见String类。通过三个范例讲解:观察String型变量、"+"操作符的使用问题及转义字符的应用。String不是基本数据类型而是引用类型,但使用方式类似基本类型。课程涵盖字符串连接、数学运算与字符串混合使用时的注意事项以及常用转义字符的用法。
|
6天前
|
存储 Java 编译器
课时11:综合实战:简单Java类
本次分享的主题是综合实战:简单 Java 类。主要分为两个部分: 1.简单 Java 类的含义 2.简单 Java 类的开发
|
7天前
|
传感器 监控 Java
Java代码结构解析:类、方法、主函数(1分钟解剖室)
### Java代码结构简介 掌握Java代码结构如同拥有程序世界的建筑蓝图,类、方法和主函数构成“黄金三角”。类是独立的容器,承载成员变量和方法;方法实现特定功能,参数控制输入环境;主函数是程序入口。常见错误包括类名与文件名不匹配、忘记static修饰符和花括号未闭合。通过实战案例学习电商系统、游戏角色控制和物联网设备监控,理解类的作用、方法类型和主函数任务,避免典型错误,逐步提升编程能力。 **脑图速记法**:类如太空站,方法即舱段;main是发射台,static不能换;文件名对仗,括号要成双;参数是坐标,void不返航。
28 5
|
6天前
|
Oracle Java 关系型数据库
课时37:综合实战:数据表与简单Java类映射转换
今天我分享的是数据表与简单 Java 类映射转换,主要分为以下四部分。 1. 映射关系基础 2. 映射步骤方法 3. 项目对象配置 4. 数据获取与调试
|
1月前
|
安全 Java 编译器
JAVA泛型类的使用(二)
接上一篇继续介绍Java泛型的高级特性。3. **编译时类型检查**:尽管运行时发生类型擦除,编译器会在编译阶段进行严格类型检查,并允许通过`extends`关键字对类型参数进行约束,确保类型安全。4. **桥方法**:为保证多态性,编译器会生成桥方法以处理类型擦除带来的问题。5. **运行时获取泛型信息**:虽然泛型信息在运行时被擦除,但可通过反射机制部分恢复这些信息,例如使用`ParameterizedType`来获取泛型参数的实际类型。
|
1月前
|
安全 Java 编译器
JAVA泛型类的使用(一)
Java 泛型类是 JDK 5.0 引入的重要特性,提供编译时类型安全检测,增强代码可读性和可维护性。通过定义泛型类如 `Box<T>`,允许使用类型参数。其核心原理是类型擦除,即编译时将泛型类型替换为边界类型(通常是 Object),确保与旧版本兼容并优化性能。例如,`Box<T>` 编译后变为 `Box<Object>`,从而实现无缝交互和减少内存开销。
|
4月前
|
Java 开发者
在 Java 中,一个类可以实现多个接口吗?
这是 Java 面向对象编程的一个重要特性,它提供了极大的灵活性和扩展性。
223 58
|
3月前
|
JSON Java Apache
Java基础-常用API-Object类
继承是面向对象编程的重要特性,允许从已有类派生新类。Java采用单继承机制,默认所有类继承自Object类。Object类提供了多个常用方法,如`clone()`用于复制对象,`equals()`判断对象是否相等,`hashCode()`计算哈希码,`toString()`返回对象的字符串表示,`wait()`、`notify()`和`notifyAll()`用于线程同步,`finalize()`在对象被垃圾回收时调用。掌握这些方法有助于更好地理解和使用Java中的对象行为。
|
4月前
|
存储 缓存 算法
面试官:单核 CPU 支持 Java 多线程吗?为什么?被问懵了!
本文介绍了多线程环境下的几个关键概念,包括时间片、超线程、上下文切换及其影响因素,以及线程调度的两种方式——抢占式调度和协同式调度。文章还讨论了减少上下文切换次数以提高多线程程序效率的方法,如无锁并发编程、使用CAS算法等,并提出了合理的线程数量配置策略,以平衡CPU利用率和线程切换开销。
面试官:单核 CPU 支持 Java 多线程吗?为什么?被问懵了!
|
4月前
|
存储 算法 Java
大厂面试高频:什么是自旋锁?Java 实现自旋锁的原理?
本文详解自旋锁的概念、优缺点、使用场景及Java实现。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
大厂面试高频:什么是自旋锁?Java 实现自旋锁的原理?

热门文章

最新文章