主页还有其他的面试资料,有需要的可以去看一下,喜欢的就留个三连再走吧~
1.发现错误:
首先我在网上搜了对象的生命周期看到的答案确实错的,他那篇文章给的确实类的加载,我人傻了
看截图:
这个是错误的!!!!!
2.什么是对象的生命周期?
生命周期是指一个对象从创建到销毁的整个过程
2.1分为的阶段:
(1)创建(Creation)
过程:
-
类加载:如果类尚未加载,JVM 会先加载类。
-
内存分配:在堆中为对象分配内存。
初始化:
-
设置对象的默认值(如 0、null、false)。
-
调用构造方法进行初始化。
触发条件:
-
使用 new 关键字创建对象。
-
使用反射(如 Class.newInstance())创建对象。
-
使用反序列化(如 ObjectInputStream.readObject())创建对象。
(2)使用(Usage)
过程:
-
对象被程序引用并执行其方法或访问其字段。
特点:
-
对象在堆内存中存活,可以被多个线程共享。
-
对象的字段和方法可以被访问和修改。
(3)不可达(Unreachable)
过程:
-
当对象不再被任何强引用(Strong Reference)引用时,对象进入不可达状态。
触发条件:
-
对象的引用被显式设置为 null。
-
对象的引用超出作用域。
-
对象的引用被重新赋值。
特点:
-
对象仍然存在于堆内存中,但无法通过程序访问。
(补充)可达对象:
-
如果一个对象可以通过强引用链从 GC Roots(如栈帧中的局部变量、静态变量等)访问到,则该对象是可达的。
(4)可回收(Eligible for GC)
过程:
-
当对象进入不可达状态后,JVM 的垃圾回收器(Garbage Collector, GC)会将其标记为可回收。
触发条件:
-
对象不再被任何强引用引用。
-
对象只被弱引用(Weak Reference)、软引用(Soft Reference)或虚引用(Phantom Reference)引用。
特点:
-
对象仍然存在于堆内存中,但随时可能被垃圾回收器回收。
(5)回收(Reclaimed)
过程:
-
垃圾回收器回收对象占用的内存。
触发条件:
-
垃圾回收器运行时,发现对象不可达。
特点:
-
对象的内存被释放,对象被销毁。
(6)终结(Finalization)
过程:
-
如果对象重写了 finalize() 方法,垃圾回收器会在回收对象之前调用该方法。
触发条件:
-
对象被标记为可回收,且重写了 finalize() 方法。
特点:
-
finalize() 方法只会被调用一次。
-
finalize() 方法可能会延迟对象的回收。
2.2.Java 提供了四种引用类型,影响对象的生命周期(相关知识点):
- 强引用(Strong Reference)(最常见):最常见的引用类型。只要强引用存在,对象就不会被回收。 示例:Object obj = new Object();
- 软引用(Soft Reference):在内存不足时,垃圾回收器会回收软引用对象。
示例:SoftReference<Object> softRef = new SoftReference<>(new Object());
- 弱引用(Weak Reference):垃圾回收器运行时,会回收弱引用对象。
示例:WeakReference<Object> weakRef = new WeakReference<>(new Object());
- 虚引用(Phantom Reference):虚引用不会影响对象的生命周期,主要用于跟踪对象被回收的状态。
示例:PhantomReference<Object> phantomRef = new PhantomReference<>(new Object(), new ReferenceQueue<>());
3.什么是类的加载?
3.1.什么是类的加载过程
一个Java文件从编码完成到最终运行,一般会经历两个阶段:编译期、运行期。编译,即通过javac命令,将Java文件转化为二进制字节码文件,即.class文件;运行,则是将.class文件交给JVM执行。而本文所说的类加载过程就是将.class文件中类的元信息加载进内存,创建Class对象并进行解析、初始化类变量等的过程
JVM并不是一开始就会将所有的类加载到内存,而是用到某个类,才会去加载,只加载一次,后续会说到类的加载时机
3.2.类加载过程
(1)加载(Loading)
任务:
-
将类的字节码文件(.class 文件)加载到内存中。
过程:
-
通过类的全限定名(包名 + 类名)获取类的字节码文件。
-
将字节码文件转换为方法区中的运行时数据结构。
-
在堆中生成一个代表该类的 java.lang.Class 对象,作为方法区数据的访问入口。
加载来源:
-
本地文件系统。
-
JAR 包。
-
网络。
-
动态生成(如动态代理)。
(2)链接(Linking)
链接主要分为三个步骤,有些文章把他直接拆开了来说
1.验证(Verification)
任务:
- 确保加载的字节码文件符合 JVM 规范,防止恶意代码破坏 JVM。
验证内容:
- 文件格式验证:检查字节码文件是否符合 Class 文件格式规范。
- 元数据验证:检查类的元数据(如父类、接口、字段、方法)是否符合 Java 语言规范。
- 字节码验证:检查方法体的字节码是否合法。
- 符号引用验证:检查符号引用(如类、方法、字段)是否能正确解析。
2.准备(Preparation)
任务:
- 为类的静态变量分配内存并设置初始值。
注意事项:
- 静态变量的初始值是数据类型的默认值(如 0、null、false)。
- 如果静态变量是常量(final),则直接赋值为代码中定义的值。
3.解析(Resolution)
任务:
- 将常量池中的符号引用替换为直接引用。
符号引用:
- 一组符号(如类名、方法名、字段名)来描述引用的目标。
直接引用:
- 指向目标的指针、偏移量或句柄。
解析内容:
- 类或接口的解析。
- 字段解析。
- 方法解析。
- 接口方法解析。
(3)初始化(Initialization)
任务:
- 执行类的初始化代码(如静态变量赋值、静态代码块)。
触发条件:
- 创建类的实例。
- 访问类的静态变量或静态方法。
- 使用反射调用类。
- 初始化子类时,父类会先被初始化。
注意事项:
- 初始化是类加载的最后一步,此时类才真正可用。
- 初始化过程是线程安全的,JVM 会加锁确保只有一个线程执行初始化。
(4)使用(Using)
(5)卸载(Unloading)
3.3.类加载的时机
类加载是懒加载的,只有在第一次使用时才会触发加载。具体时机包括
- 创建类的实例(new)
- 访问类的静态变量或静态方法
- 使用反射调用类(如 Class.forName())
- 初始化子类时,父类会先被初始化
- JVM 启动时,加载包含 main() 方法的类
3.4.类加载器(ClassLoader)
类加载器通过双亲委派模型确保类的唯一性和安全性
类加载过程由类加载器完成。
JVM 提供了以下类加载器:
- Bootstrap ClassLoader
- Extension ClassLoader
- Application ClassLoader
- 自定义 ClassLoader
4.思维导图:
5.相关文章(里面有其他内容):
JVM篇(这篇文章的内容在这里,一万多字):https://blog.youkuaiyun.com/TLOVEYOUTOO/article/details/145689832?spm=1001.2014.3001.5502
Java基础篇(三万多字):
https://blog.youkuaiyun.com/TLOVEYOUTOO/article/details/145653870?spm=1001.2014.3001.5502