Skip to content

Commit e768e5f

Browse files
committed
比亚迪面试
1 parent f8c320e commit e768e5f

File tree

6 files changed

+203
-121
lines changed

6 files changed

+203
-121
lines changed

docs/sidebar/sanfene/javase.md

Lines changed: 41 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ GitHub 上标星 10000+ 的开源知识库《[二哥的 Java 进阶之路](https
311311

312312
### 16.面向对象编程有哪些特性?
313313

314-
推荐阅读:[深入理解Java三大特性](https://javabetter.cn/oo/encapsulation-inheritance-polymorphism.html)
314+
推荐阅读:[深入理解 Java 三大特性](https://javabetter.cn/oo/encapsulation-inheritance-polymorphism.html)
315315

316316
面向对象编程有三大特性:封装、继承、多态。
317317

@@ -373,7 +373,7 @@ Student 类继承了 Person 类的属性(name、age)和方法(eat),同
373373

374374
#### 什么是多态?
375375

376-
推荐阅读:[深入理解Java三大特性:封装、继承和多态](https://javabetter.cn/oo/encapsulation-inheritance-polymorphism.html)
376+
推荐阅读:[深入理解 Java 三大特性:封装、继承和多态](https://javabetter.cn/oo/encapsulation-inheritance-polymorphism.html)
377377

378378
多态允许不同类的对象对同一消息做出响应,但表现出不同的行为(即方法的多样性)。
379379

@@ -412,7 +412,7 @@ class Wanger {
412412

413413
### 55.多态解决了什么问题?(补充)
414414

415-
>2024年03月26日增补
415+
> 2024 年 03 月 26 日增补
416416
417417
多态的目的是为了提高代码的灵活性和可扩展性,使得代码更容易维护和扩展。比如说动态绑定,允许在程序在运行时再确定调用的是子类还是父类的方法。
418418

@@ -1420,36 +1420,57 @@ InputStream 相关的部分类图如下,篇幅有限,装饰器模式就不
14201420

14211421
> 1. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的国企面试原题:文本存储是字节流还是字符流,视频文件呢?
14221422
1423-
### 44.BIO、NIO、AIO?
1423+
### 44.BIO、NIO、AIO 之间的区别
14241424

1425-
![BIO、NIO、AIO](https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/sidebar/sanfene/javase-26.png)
1425+
推荐阅读:[Java NIO 比传统 IO 强在哪里?](https://javabetter.cn/nio/nio-better-io.html)
14261426

1427-
**BIO**(blocking I/O) : 就是传统的 IO,同步阻塞,服务器实现模式为一个连接一个线程,即**客户端有连接请求时服务器端就需要启动一个线程进行处理**,如果这个连接不做任何事情会造成不必要的线程开销,可以通过连接池机制改善(实现多个客户连接服务器)
1427+
BIO(Blocking I/O):采用阻塞式 I/O 模型,线程在执行 I/O 操作时被阻塞,无法处理其他任务,适用于连接数较少的场景
14281428

1429-
![BIO、NIO、AIO](https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/sidebar/sanfene/javase-27.png)
1429+
NIO(New I/O 或 Non-blocking I/O):采用非阻塞 I/O 模型,线程在等待 I/O 时可执行其他任务,通过 Selector 监控多个 Channel 上的事件,适用于连接数多但连接时间短的场景。
14301430

1431-
BIO 方式适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4 以前的唯一选择,程序简单易理解
1431+
AIO(Asynchronous I/O):使用异步 I/O 模型,线程发起 I/O 请求后立即返回,当 I/O 操作完成时通过回调函数通知线程,适用于连接数多且连接时间长的场景
14321432

1433-
**NIO** :全称 java non-blocking IO,是指 JDK 提供的新 API。从 JDK1.4 开始,Java 提供了一系列改进的输入/输出的新特性,被统称为 NIO(即 New IO)。
1433+
![](https://cdn.tobebetterjavaer.com/stutymore/javase-20240404103618.png)
14341434

1435-
NIO 是**同步非阻塞**的,服务器端用一个线程处理多个连接,客户端发送的连接请求会注册到多路复用器上,多路复用器轮询到连接有 IO 请求就进行处理:
1435+
#### 简单说一下 BIO?
14361436

1437-
![NIO线程](https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/sidebar/sanfene/javase-28.png)
1437+
BIO,也就是传统的 IO,基于字节流或字符流(如 FileInputStream、BufferedReader 等)进行文件读写,基于 Socket 和 ServerSocket 进行网络通信。
14381438

1439-
NIO 的数据是面向**缓冲区 Buffer**的,必须从 Buffer 中读取或写入
1439+
对于每个连接,都需要创建一个独立的线程来处理读写操作
14401440

1441-
所以完整的 NIO 示意图:
1441+
![三分恶面渣逆袭:BIO](https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/sidebar/sanfene/javase-27.png)
14421442

1443-
![NIO完整示意图](https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/sidebar/sanfene/javase-29.png)
1443+
#### 简单说下 NIO?
14441444

1445-
可以看出,NIO 的运行机制:
1445+
NIO,JDK 1.4 时引入,放在 java.nio 包下,提供了 Channel、Buffer、Selector 等新的抽象,基于 RandomAccessFile、FileChannel、ByteBuffer 进行文件读写,基于 SocketChannel 和 ServerSocketChannel 进行网络通信。
14461446

1447-
- 每个 Channel 对应一个 Buffer。
1448-
- Selector 对应一个线程,一个线程对应多个 Channel。
1449-
- Selector 会根据不同的事件,在各个通道上切换。
1450-
- Buffer 是内存块,底层是数据。
1447+
实际上,“旧”的 I/O 包已经使用 NIO 重新实现过,所以在进行文件读写时,NIO 并无法体现出比 BIO 更可靠的性能。
14511448

1452-
**AIO**:JDK 7 引入了 Asynchronous I/O,是**异步不阻塞**的 IO。在进行 I/O 编程中,常用到两种模式:Reactor 和 Proactor。Java 的 NIO 就是 Reactor,当有事件触发时,服务器端得到通知,进行相应的处理,完成后才通知服务端程序启动线程去处理,一般适用于连接数较多且连接时间较长的应用。
1449+
NIO 的魅力主要体现在网络编程中,服务器可以用一个线程处理多个客户端连接,通过 Selector 监听多个 Channel 来实现多路复用,极大地提高了网络编程的性能。
1450+
1451+
![三分恶面渣逆袭:NIO](https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/sidebar/sanfene/javase-28.png)
1452+
1453+
缓冲区 Buffer 也能极大提升一次 IO 操作的效率。
1454+
1455+
![三分恶面渣逆袭:NIO完整示意图](https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/sidebar/sanfene/javase-29.png)
1456+
1457+
#### 简单说下 AIO?
1458+
1459+
AIO 是 Java 7 引入的,放在 java.nio.channels 包下,提供了 AsynchronousFileChannel、AsynchronousSocketChannel 等异步 Channel。
1460+
1461+
它引入了异步通道的概念,使得I/O操作可以异步进行。这意味着线程发起一个读写操作后不必等待其完成,可以立即进行其他任务,并且当读写操作真正完成时,线程会被异步地通知。
1462+
1463+
```java
1464+
AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(Paths.get("test.txt"), StandardOpenOption.READ);
1465+
ByteBuffer buffer = ByteBuffer.allocate(1024);
1466+
Future<Integer> result = fileChannel.read(buffer, 0);
1467+
while (!result.isDone()) {
1468+
// do something
1469+
}
1470+
```
1471+
1472+
1473+
> 1. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的比亚迪面经同学 3 Java 技术一面面试原题:BIO NIO 的区别
14531474
14541475
## 序列化
14551476

docs/sidebar/sanfene/javathread.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -929,7 +929,7 @@ JMM 定义了线程内存和主内存之间的抽象关系:线程之间的共
929929

930930
每个核都有自己的一级缓存,在有些架构里面还有一个所有 CPU 共享的二级缓存。
931931

932-
Java 内存模型里面的本地内存,可能对应的事 L1 缓存或者 L2 缓存或者 CPU 寄存器。
932+
Java 内存模型里面的本地内存,可能对应的是 L1 缓存或者 L2 缓存或者 CPU 寄存器。
933933

934934
#### 为什么线程要用自己的内存?
935935

@@ -938,6 +938,7 @@ Java 内存模型里面的本地内存,可能对应的事 L1 缓存或者 L2
938938
第二,现代 CPU 为了优化执行效率,可能会对指令进行乱序执行(指令重排序)。使用本地内存(CPU 缓存和寄存器)可以在不影响最终执行结果的前提下,使得 CPU 有更大的自由度来乱序执行指令,从而提高执行效率。
939939

940940
> 1. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的帆软同学 3 Java 后端一面的原题:为什么线程要用自己的内存
941+
> 2. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的比亚迪面经同学 3 Java 技术一面面试原题:说一下 JMM
941942
942943
### 19.说说你对原子性、可见性、有序性的理解?
943944

docs/sidebar/sanfene/jvm.md

Lines changed: 33 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -106,57 +106,58 @@ ZGC 是 JDK11 推出的一款低延迟垃圾收集器,适用于大内存低延
106106

107107
推荐阅读:[深入理解 JVM 的运行时数据区](https://javabetter.cn/jvm/neicun-jiegou.html)
108108

109-
JVM 的内存区域可以粗暴地划分为````,当然了,按照 Java 的虚拟机规范,可以再细分为`程序计数器``虚拟机栈``本地方法栈````方法区`等。
109+
JVM 的内存区域,有时也叫 JVM 运行时数据区,可以粗暴地划分为````,当然了,按照 Java 的虚拟机规范,可以再细分为`程序计数器``虚拟机栈``本地方法栈````方法区`等。
110110

111111
![三分恶面渣逆袭:Java虚拟机运行时数据区](https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/sidebar/sanfene/jvm-3.png)
112112

113-
其中`方法区```是线程共享区`虚拟机栈``本地方法栈``程序计数器`是线程私有的。
113+
其中`方法区```是线程共享的`虚拟机栈``本地方法栈``程序计数器`是线程私有的。
114114

115-
#### 程序计数器
115+
#### 介绍一下程序计数器?
116116

117117
程序计数器(Program Counter Register)也被称为 PC 寄存器,是一块较小的内存空间。它可以看作是当前线程所执行的字节码行号指示器。
118118

119-
#### Java 虚拟机栈
119+
#### 介绍一下 Java 虚拟机栈
120120

121121
Java 虚拟机栈(Java Virtual Machine Stack),通常指的就是“栈”,它的生命周期与线程相同。
122122

123-
Java 虚拟机栈(JVM 栈)中是一个个[栈帧](https://javabetter.cn/jvm/stack-frame.html)每个栈帧对应一个被调用的方法。当线程执行一个方法时,会创建一个对应的栈帧,并将栈帧压入栈中。当方法执行完毕后,将栈帧从栈中移除
123+
当线程执行一个方法时,会创建一个对应的[栈帧](https://javabetter.cn/jvm/stack-frame.html)用于存储局部变量表、操作数栈、动态链接、方法出口等信息,然后栈帧会被压入栈中。当方法执行完毕后,栈帧会从栈中移除
124124

125125
![三分恶面渣逆袭:Java虚拟机栈](https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/sidebar/sanfene/jvm-4.png)
126126

127-
#### 本地方法栈
127+
#### 介绍一下本地方法栈?
128128

129-
本地方法栈(Native Method Stacks)与虚拟机栈相似,区别在于虚拟机栈是为虚拟机执行 Java 方法服务的,而本地方法栈是为虚拟机使用到的本地(Native)方法服务的
129+
本地方法栈(Native Method Stacks)与虚拟机栈相似,区别在于虚拟机栈是为 JVM 执行 Java 编写的方法服务的,而本地方法栈是为 Java 调用[本地(native)方法](https://javabetter.cn/oo/native-method.html)服务的,由 C/C++ 编写
130130

131-
#### Java 堆
131+
#### 介绍一下 Java 堆
132132

133-
Java 堆(Java Heap)是虚拟机所管理的内存中最大的一块,被所有线程共享,在虚拟机启动时创建
133+
堆(heap)是 JVM 中最大的一块内存区域,被所有线程共享,在 JVM 启动时创建,主要用来存储对象的
134134

135135
![](https://cdn.tobebetterjavaer.com/stutymore/neicun-jiegou-20231225154450.png)
136136

137-
以前,Java 中“几乎”所有的对象都会在堆中分配,但随着 JIT 编译器的发展和逃逸技术的逐渐成熟,所有的对象都分配到堆上渐渐变得不那么“绝对”了
137+
以前,Java 中“几乎”所有的对象都会在堆中分配,但随着 [JIT 编译器](https://javabetter.cn/jvm/jit.html)的发展和逃逸技术的逐渐成熟,“所有的对象都会分配到堆上”就不再那么绝对了
138138

139-
从 JDK 7 开始,Java 虚拟机已经默认开启逃逸分析了,意味着如果某些方法中的对象引用没有被返回或者未被外面使用(也就是未逃逸出去),那么对象可以直接在栈上分配内存。
139+
从 JDK 7 开始,JVM 已经默认开启逃逸分析了,意味着如果某些方法中的对象引用没有被返回或者未被方法体外使用(也就是未逃逸出去),那么对象可以直接在栈上分配内存。
140140

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)。
142142

143-
从回收内存的角度来看,由于垃圾收集器大部分都是基于分代收集理论设计的,所以 Java 堆中经常会出现`新生代``老年代``Eden空间``From Survivor空间``To Survivor空间`等名词
143+
从内存回收的角度来看,由于垃圾收集器大部分都是基于分代收集理论设计的,所以堆也会被划分为`新生代``老年代``Eden空间``From Survivor空间``To Survivor空间`
144144

145145
![三分恶面渣逆袭:Java 堆内存结构](https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/sidebar/sanfene/jvm-5.png)
146146

147-
#### 方法区
147+
#### 堆和栈的区别是什么?
148148

149-
方法区是一块比较特别的区域,和堆类似,也是各个线程共享的内存区域,用于存储已被虚拟机加载的类型信息、常量、静态变量、[即时编译器](https://javabetter.cn/jvm/jit.html)编译后的代码缓存等
149+
堆属于线程共享的内存区域,几乎所有的对象都在堆上分配,生命周期不由单个方法调用所决定,可以在方法调用结束后继续存在,直到不再被任何变量引用,然后被垃圾收集器回收
150150

151-
Java 虚拟机规范对它的约束非常宽松,所以方法区的具体实现历经了许多变迁,例如 JDK 1.7 时,方法区被永久代(Permanent Generation)所代替,而在 JDK 1.8 时,永久代被彻底移除,取而代之的是元空间(Metaspace)
151+
栈属于线程私有的内存区域,主要存储局部变量、方法参数、对象引用等,通常随着方法调用的结束而自动释放,不需要垃圾收集器处理
152152

153-
**堆和栈的区别是什么**
153+
#### 介绍一下方法区?
154154

155-
堆属于线程共享的内存区域,几乎所有的对象都在对上分配,生命周期不由单个方法调用所决定,可以在方法调用结束后继续存在,直到不在被任何变量引用,然后被垃圾收集器回收
155+
方法区并不真实存在,属于 Java 虚拟机规范中的一个逻辑概念,用于存储已被 JVM 加载的类信息、常量、静态变量、即时编译器编译后的代码缓存等
156156

157-
栈就是前面提到的 JVM 栈(主要存储局部变量、方法参数、对象引用等),属于线程私有,通常随着方法调用的结束而消失,也就无需进行垃圾收集
157+
在 HotSpot 虚拟机中,方法区的实现称为永久代(PermGen),但在 Java 8 及之后的版本中,已经被元空间(Metaspace)所替代
158158

159159
> 1. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的京东同学 10 后端实习一面的原题:堆和栈的区别是什么
160+
> 2. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的比亚迪面经同学 3 Java 技术一面面试原题:介绍一下 JVM 运行时数据区
160161
161162
### 3.说一下 JDK1.6、1.7、1.8 内存区域的变化?
162163

@@ -184,21 +185,25 @@ Java 虚拟机规范规定的方法区只是换种方式实现。有客观和主
184185

185186
### 5.对象创建的过程了解吗?
186187

187-
在 JVM 中对象的创建,我们从一个 new 指令开始:
188+
当我们使用 new 关键字创建一个对象的时候,JVM 首先会检查 new 指令的参数是否能在常量池中定位到一个类的符号引用,然后检查这个符号引用代表的类是否已被加载、解析和初始化过。如果没有,就先执行相应的类加载过程。
188189

189-
- 首先检查这个指令的参数是否能在常量池中定位到一个类的符号引用
190+
如果已经加载,JVM 会为新生对象分配内存,内存分配完成之后,JVM 将分配到的内存空间初始化为零值(成员变量,数值类型是 0,布尔类型是 false,对象类型是 null),接下来设置对象头,对象头里包含了对象是哪个类的实例、对象的哈希码、对象的 GC 分代年龄等信息。
190191

191-
- 检查这个符号引用代表的类是否已被加载、解析和初始化过。如果没有,就先执行相应的类加载过程
192+
最后,JVM 会执行构造方法(`<init>`),将成员变量赋值为预期的值,这样一个对象就创建完成了。
192193

193-
- 类加载检查通过后,接下来虚拟机将为新生对象分配内存。
194+
![](https://cdn.tobebetterjavaer.com/stutymore/jvm-20240404091445.png)
194195

195-
- 内存分配完成之后,虚拟机将分配到的内存空间(但不包括对象头)都初始化为零值。
196+
#### 对象的销毁过程了解吗?
196197

197-
- 接下来设置对象头,请求头里包含了对象是哪个类的实例、如何才能找到类的元数据信息、对象的哈希码、对象的 GC 分代年龄等信息
198+
对象创建完成后,就可以通过引用来访问对象的方法和属性,当对象不再被任何引用指向时,对象就会变成垃圾
198199

199-
这个过程大概图示如下:
200+
垃圾收集器会通过可达性分析算法判断对象是否存活,如果对象不可达,就会被回收。
200201

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 技术一面面试原题:对象创建到销毁的流程
202207
203208
### 6.什么是指针碰撞?什么是空闲列表?
204209

@@ -1361,7 +1366,6 @@ JVM 的操作对象是 Class 文件,JVM 把 Class 文件中描述类的数据
13611366

13621367
> 1. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的小米暑期实习同学 E 一面面试原题:你了解类的加载机制吗?
13631368
1364-
13651369
### 42.能说一下类的生命周期吗?
13661370

13671371
一个类从被加载到虚拟机内存中开始,到从内存中卸载,整个生命周期需要经过七个阶段:加载 (Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)、初始化 (Initialization)、使用(Using)和卸载(Unloading),其中验证、准备、解析三个部分统称为连接(Linking)。
@@ -1490,7 +1494,7 @@ OSGi 实现模块化热部署的关键是它自定义的类加载器机制的实
14901494

14911495
实现一个热部署(Hot Deployment)功能通常涉及到类的加载和卸载机制,使得在不重启应用程序的情况下,能够动态替换或更新应用程序的组件。
14921496

1493-
第一步,使用文件监控机制(如Java NIO的WatchService)来监控类文件或配置文件的变更。当监控到文件变更时,触发热部署流程。
1497+
第一步,使用文件监控机制(如 Java NIO 的 WatchService)来监控类文件或配置文件的变更。当监控到文件变更时,触发热部署流程。
14941498

14951499
```java
14961500
class FileWatcher {

0 commit comments

Comments
 (0)