@@ -106,57 +106,58 @@ ZGC 是 JDK11 推出的一款低延迟垃圾收集器,适用于大内存低延
106
106
107
107
推荐阅读:[ 深入理解 JVM 的运行时数据区] ( https://javabetter.cn/jvm/neicun-jiegou.html )
108
108
109
- JVM 的内存区域可以粗暴地划分为 ` 堆 ` 和` 栈 ` ,当然了,按照 Java 的虚拟机规范,可以再细分为` 程序计数器 ` 、` 虚拟机栈 ` 、` 本地方法栈 ` 、` 堆 ` 、` 方法区 ` 等。
109
+ JVM 的内存区域,有时也叫 JVM 运行时数据区,可以粗暴地划分为 ` 堆 ` 和` 栈 ` ,当然了,按照 Java 的虚拟机规范,可以再细分为` 程序计数器 ` 、` 虚拟机栈 ` 、` 本地方法栈 ` 、` 堆 ` 、` 方法区 ` 等。
110
110
111
111
![ 三分恶面渣逆袭:Java虚拟机运行时数据区] ( https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/sidebar/sanfene/jvm-3.png )
112
112
113
- 其中` 方法区 ` 和` 堆 ` 是线程共享区 ,` 虚拟机栈 ` 、` 本地方法栈 ` 和` 程序计数器 ` 是线程私有的。
113
+ 其中` 方法区 ` 和` 堆 ` 是线程共享的 ,` 虚拟机栈 ` 、` 本地方法栈 ` 和` 程序计数器 ` 是线程私有的。
114
114
115
- #### 程序计数器
115
+ #### 介绍一下程序计数器?
116
116
117
117
程序计数器(Program Counter Register)也被称为 PC 寄存器,是一块较小的内存空间。它可以看作是当前线程所执行的字节码行号指示器。
118
118
119
- #### Java 虚拟机栈
119
+ #### 介绍一下 Java 虚拟机栈?
120
120
121
121
Java 虚拟机栈(Java Virtual Machine Stack),通常指的就是“栈”,它的生命周期与线程相同。
122
122
123
- Java 虚拟机栈(JVM 栈)中是一个个 [ 栈帧] ( https://javabetter.cn/jvm/stack-frame.html ) ,每个栈帧对应一个被调用的方法。当线程执行一个方法时,会创建一个对应的栈帧,并将栈帧压入栈中 。当方法执行完毕后,将栈帧从栈中移除 。
123
+ 当线程执行一个方法时,会创建一个对应的 [ 栈帧] ( https://javabetter.cn/jvm/stack-frame.html ) ,用于存储局部变量表、操作数栈、动态链接、方法出口等信息,然后栈帧会被压入栈中 。当方法执行完毕后,栈帧会从栈中移除 。
124
124
125
125
![ 三分恶面渣逆袭:Java虚拟机栈] ( https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/sidebar/sanfene/jvm-4.png )
126
126
127
- #### 本地方法栈
127
+ #### 介绍一下本地方法栈?
128
128
129
- 本地方法栈(Native Method Stacks)与虚拟机栈相似,区别在于虚拟机栈是为虚拟机执行 Java 方法服务的,而本地方法栈是为虚拟机使用到的本地(Native)方法服务的 。
129
+ 本地方法栈(Native Method Stacks)与虚拟机栈相似,区别在于虚拟机栈是为 JVM 执行 Java 编写的方法服务的,而本地方法栈是为 Java 调用 [ 本地(native)方法 ] ( https://javabetter.cn/oo/native-method.html ) 服务的,由 C/C++ 编写 。
130
130
131
- #### Java 堆
131
+ #### 介绍一下 Java 堆?
132
132
133
- Java 堆(Java Heap)是虚拟机所管理的内存中最大的一块 ,被所有线程共享,在虚拟机启动时创建 。
133
+ 堆(heap)是 JVM 中最大的一块内存区域 ,被所有线程共享,在 JVM 启动时创建,主要用来存储对象的 。
134
134
135
135
![ ] ( https://cdn.tobebetterjavaer.com/stutymore/neicun-jiegou-20231225154450.png )
136
136
137
- 以前,Java 中“几乎”所有的对象都会在堆中分配,但随着 JIT 编译器的发展和逃逸技术的逐渐成熟,所有的对象都分配到堆上渐渐变得不那么“绝对”了 。
137
+ 以前,Java 中“几乎”所有的对象都会在堆中分配,但随着 [ JIT 编译器 ] ( https://javabetter.cn/jvm/jit.html ) 的发展和逃逸技术的逐渐成熟,“所有的对象都会分配到堆上”就不再那么绝对了 。
138
138
139
- 从 JDK 7 开始,Java 虚拟机已经默认开启逃逸分析了,意味着如果某些方法中的对象引用没有被返回或者未被外面使用 (也就是未逃逸出去),那么对象可以直接在栈上分配内存。
139
+ 从 JDK 7 开始,JVM 已经默认开启逃逸分析了,意味着如果某些方法中的对象引用没有被返回或者未被方法体外使用 (也就是未逃逸出去),那么对象可以直接在栈上分配内存。
140
140
141
- Java 堆是 [ 垃圾收集器] ( https://javabetter.cn/jvm/gc-collector.html ) 管理的内存区域,因此一些资料中它也被称作 “GC 堆”(Garbage Collected Heap)。
141
+ 堆也是 [ 垃圾收集器] ( https://javabetter.cn/jvm/gc-collector.html ) 管理的目标区域,因此一些资料中也会把 Java 堆称作 “GC 堆”(Garbage Collected Heap)。
142
142
143
- 从回收内存的角度来看 ,由于垃圾收集器大部分都是基于分代收集理论设计的,所以 Java 堆中经常会出现 ` 新生代 ` 、` 老年代 ` 、` Eden空间 ` 、` From Survivor空间 ` 、` To Survivor空间 ` 等名词 。
143
+ 从内存回收的角度来看 ,由于垃圾收集器大部分都是基于分代收集理论设计的,所以堆也会被划分为 ` 新生代 ` 、` 老年代 ` 、` Eden空间 ` 、` From Survivor空间 ` 、` To Survivor空间 ` 等 。
144
144
145
145
![ 三分恶面渣逆袭:Java 堆内存结构] ( https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/sidebar/sanfene/jvm-5.png )
146
146
147
- #### 方法区
147
+ #### 堆和栈的区别是什么?
148
148
149
- 方法区是一块比较特别的区域,和堆类似,也是各个线程共享的内存区域,用于存储已被虚拟机加载的类型信息、常量、静态变量、 [ 即时编译器 ] ( https://javabetter.cn/jvm/jit.html ) 编译后的代码缓存等 。
149
+ 堆属于线程共享的内存区域,几乎所有的对象都在堆上分配,生命周期不由单个方法调用所决定,可以在方法调用结束后继续存在,直到不再被任何变量引用,然后被垃圾收集器回收 。
150
150
151
- Java 虚拟机规范对它的约束非常宽松,所以方法区的具体实现历经了许多变迁,例如 JDK 1.7 时,方法区被永久代(Permanent Generation)所代替,而在 JDK 1.8 时,永久代被彻底移除,取而代之的是元空间(Metaspace) 。
151
+ 栈属于线程私有的内存区域,主要存储局部变量、方法参数、对象引用等,通常随着方法调用的结束而自动释放,不需要垃圾收集器处理 。
152
152
153
- ** 堆和栈的区别是什么 **
153
+ #### 介绍一下方法区?
154
154
155
- 堆属于线程共享的内存区域,几乎所有的对象都在对上分配,生命周期不由单个方法调用所决定,可以在方法调用结束后继续存在,直到不在被任何变量引用,然后被垃圾收集器回收 。
155
+ 方法区并不真实存在,属于 Java 虚拟机规范中的一个逻辑概念,用于存储已被 JVM 加载的类信息、常量、静态变量、即时编译器编译后的代码缓存等 。
156
156
157
- 栈就是前面提到的 JVM 栈(主要存储局部变量、方法参数、对象引用等),属于线程私有,通常随着方法调用的结束而消失,也就无需进行垃圾收集 。
157
+ 在 HotSpot 虚拟机中,方法区的实现称为永久代(PermGen),但在 Java 8 及之后的版本中,已经被元空间(Metaspace)所替代 。
158
158
159
159
> 1 . [ Java 面试指南(付费)] ( https://javabetter.cn/zhishixingqiu/mianshi.html ) 收录的京东同学 10 后端实习一面的原题:堆和栈的区别是什么
160
+ > 2 . [ Java 面试指南(付费)] ( https://javabetter.cn/zhishixingqiu/mianshi.html ) 收录的比亚迪面经同学 3 Java 技术一面面试原题:介绍一下 JVM 运行时数据区
160
161
161
162
### 3.说一下 JDK1.6、1.7、1.8 内存区域的变化?
162
163
@@ -184,21 +185,25 @@ Java 虚拟机规范规定的方法区只是换种方式实现。有客观和主
184
185
185
186
### 5.对象创建的过程了解吗?
186
187
187
- 在 JVM 中对象的创建,我们从一个 new 指令开始:
188
+ 当我们使用 new 关键字创建一个对象的时候,JVM 首先会检查 new 指令的参数是否能在常量池中定位到一个类的符号引用,然后检查这个符号引用代表的类是否已被加载、解析和初始化过。如果没有,就先执行相应的类加载过程。
188
189
189
- - 首先检查这个指令的参数是否能在常量池中定位到一个类的符号引用
190
+ 如果已经加载,JVM 会为新生对象分配内存,内存分配完成之后,JVM 将分配到的内存空间初始化为零值(成员变量,数值类型是 0,布尔类型是 false,对象类型是 null),接下来设置对象头,对象头里包含了对象是哪个类的实例、对象的哈希码、对象的 GC 分代年龄等信息。
190
191
191
- - 检查这个符号引用代表的类是否已被加载、解析和初始化过。如果没有,就先执行相应的类加载过程
192
+ 最后,JVM 会执行构造方法( ` <init> ` ),将成员变量赋值为预期的值,这样一个对象就创建完成了。
192
193
193
- - 类加载检查通过后,接下来虚拟机将为新生对象分配内存。
194
+ ![ ] ( https://cdn.tobebetterjavaer.com/stutymore/jvm-20240404091445.png )
194
195
195
- - 内存分配完成之后,虚拟机将分配到的内存空间(但不包括对象头)都初始化为零值。
196
+ #### 对象的销毁过程了解吗?
196
197
197
- - 接下来设置对象头,请求头里包含了对象是哪个类的实例、如何才能找到类的元数据信息、对象的哈希码、对象的 GC 分代年龄等信息 。
198
+ 对象创建完成后,就可以通过引用来访问对象的方法和属性,当对象不再被任何引用指向时,对象就会变成垃圾 。
198
199
199
- 这个过程大概图示如下:
200
+ 垃圾收集器会通过可达性分析算法判断对象是否存活,如果对象不可达,就会被回收。
200
201
201
- ![ 对象创建过程] ( https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/sidebar/sanfene/jvm-9.png )
202
+ 垃圾收集器会通过标记清除、标记复制、标记整理等算法来回收内存,将对象占用的内存空间释放出来。
203
+
204
+ 常用的垃圾收集器有 CMS、G1、ZGC 等,它们的回收策略和效率不同,可以根据具体的场景选择合适的垃圾收集器。
205
+
206
+ > 1 . [ Java 面试指南(付费)] ( https://javabetter.cn/zhishixingqiu/mianshi.html ) 收录的比亚迪面经同学 3 Java 技术一面面试原题:对象创建到销毁的流程
202
207
203
208
### 6.什么是指针碰撞?什么是空闲列表?
204
209
@@ -1361,7 +1366,6 @@ JVM 的操作对象是 Class 文件,JVM 把 Class 文件中描述类的数据
1361
1366
1362
1367
> 1 . [ Java 面试指南(付费)] ( https://javabetter.cn/zhishixingqiu/mianshi.html ) 收录的小米暑期实习同学 E 一面面试原题:你了解类的加载机制吗?
1363
1368
1364
-
1365
1369
### 42.能说一下类的生命周期吗?
1366
1370
1367
1371
一个类从被加载到虚拟机内存中开始,到从内存中卸载,整个生命周期需要经过七个阶段:加载 (Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)、初始化 (Initialization)、使用(Using)和卸载(Unloading),其中验证、准备、解析三个部分统称为连接(Linking)。
@@ -1490,7 +1494,7 @@ OSGi 实现模块化热部署的关键是它自定义的类加载器机制的实
1490
1494
1491
1495
实现一个热部署(Hot Deployment)功能通常涉及到类的加载和卸载机制,使得在不重启应用程序的情况下,能够动态替换或更新应用程序的组件。
1492
1496
1493
- 第一步,使用文件监控机制(如Java NIO的WatchService )来监控类文件或配置文件的变更。当监控到文件变更时,触发热部署流程。
1497
+ 第一步,使用文件监控机制(如 Java NIO 的 WatchService )来监控类文件或配置文件的变更。当监控到文件变更时,触发热部署流程。
1494
1498
1495
1499
``` java
1496
1500
class FileWatcher {
0 commit comments