Skip to content

Commit 8f8e07c

Browse files
committed
更改目录
1 parent 4dc2e1c commit 8f8e07c

35 files changed

+550
-203
lines changed

Java/JVM.md

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ Java 内存模型(JMM)是基于共享内存的多线程通信机制。
9090

9191
JVM内存结构 = 类加载器 + 执行引擎 + 运行时数据区域 。
9292

93-
![image-20210905150636105](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210905150636105.png)
93+
![image-20210905150636105](http://img.dabin-coder.cn/image/image-20210905150636105.png)
9494

9595
> 图片来源:深入理解Java虚拟机-周志明
9696
@@ -172,11 +172,11 @@ JDK 1.8 的时候,HotSpot 的永久代被彻底移除了,使用元空间替
172172

173173
运行时常量池是方法区的一部分,在类加载之后,会将编译器生成的各种字面量和符号引号放到运行时常量池。在运行期间动态生成的常量,如 String 类的 intern()方法,也会被放入运行时常量池。
174174

175-
![](https://raw.githubusercontent.com/Tyson0314/img/master/string-new.png)
175+
![](http://img.dabin-coder.cn/image/string-new.png)
176176

177-
![](https://raw.githubusercontent.com/Tyson0314/img/master/string-intern.png)
177+
![](http://img.dabin-coder.cn/image/string-intern.png)
178178

179-
![](https://raw.githubusercontent.com/Tyson0314/img/master/string-equal.png)
179+
![](http://img.dabin-coder.cn/image/string-equal.png)
180180

181181
> 图片来源:https://blog.csdn.net/soonfly
182182
@@ -194,11 +194,11 @@ Java 程序通过栈上的 reference 数据来操作堆上的具体对象。对
194194

195195
- 如果使用句柄的话,那么 Java 堆中将会划分出一块内存来作为句柄池,reference 中存储的就是对象的句柄地址,而句柄中包含了对象实例数据与类型数据各自的具体地址信息。使用句柄来访问的最大好处是 reference 中存储的是稳定的句柄地址,在对象被移动时只会改变句柄中的实例数据指针,而 reference 本身不需要修改。
196196

197-
![](https://raw.githubusercontent.com/Tyson0314/img/master/object-handle.png)
197+
![](http://img.dabin-coder.cn/image/object-handle.png)
198198

199199
- 直接指针。reference 中存储的直接就是对象的地址。对象包含到对象类型数据的指针,通过这个指针可以访问对象类型数据。使用直接指针访问方式最大的好处就是访问对象速度快,它节省了一次指针定位的时间开销,虚拟机hotspot主要是使用直接指针来访问对象。
200200

201-
![](https://raw.githubusercontent.com/Tyson0314/img/master/direct-pointer.png)
201+
![](http://img.dabin-coder.cn/image/direct-pointer.png)
202202

203203

204204

@@ -245,7 +245,7 @@ ClassFile {
245245

246246
加载、验证、准备、解析、初始化、使用和卸载。
247247

248-
![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210905002423703.png)
248+
![](http://img.dabin-coder.cn/image/image-20210905002423703.png)
249249

250250
## 类加载的过程
251251

@@ -281,7 +281,7 @@ ClassFile {
281281

282282
一个类加载器收到一个类的加载请求时,它首先不会自己尝试去加载它,而是把这个请求委派给父类加载器去完成,这样层层委派,因此所有的加载请求最终都会传送到顶层的启动类加载器中,只有当父类加载器反馈自己无法完成这个加载请求时,子加载器才会尝试自己去加载。
283283

284-
![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210905002827546.png)
284+
![](http://img.dabin-coder.cn/image/image-20210905002827546.png)
285285

286286
双亲委派模型的好处:可以防止内存中出现多份同样的字节码。如果没有双亲委派模型而是由各个类加载器自行加载的话,如果用户编写了一个java.lang.Object的同名类并放在ClassPath中,多个类加载器都去加载这个类到内存中,系统中将会出现多个不同的Object类,那么类之间的比较结果及类的唯一性将无法保证。
287287

@@ -339,7 +339,7 @@ public abstract class ClassLoader {
339339

340340
堆中几乎放着所有的对象实例,对堆垃圾回收前的第一步就是要判断那些对象已经死亡(即不能再被任何途径使用的对象)。
341341

342-
![](https://raw.githubusercontent.com/Tyson0314/img/master/object-dead.png)
342+
![](http://img.dabin-coder.cn/image/object-dead.png)
343343

344344
### 引用计数法
345345

@@ -365,7 +365,7 @@ public class ReferenceCountingGc {
365365

366366
通过GC Root对象为起点,从这些节点向下搜索,搜索所走过的路径叫引用链,当一个对象到GC Root没有任何的引用链相连时,说明这个对象是不可用的。
367367

368-
![](https://raw.githubusercontent.com/Tyson0314/img/master/gc-root-refer.png)
368+
![](http://img.dabin-coder.cn/image/gc-root-refer.png)
369369

370370
#### 可作为GC Roots的对象
371371

@@ -469,13 +469,13 @@ public class ReferenceCountingGc {
469469

470470
标记清除算法就是分为“标记”和“清除”两个阶段。标记出所有需要回收的对象,标记结束后统一回收所有被标记的对象。这种垃圾回收算法效率较低,并且会产生大量不连续的空间碎片。
471471

472-
![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210905003458130.png)
472+
![](http://img.dabin-coder.cn/image/image-20210905003458130.png)
473473

474474
### 复制清除算法
475475

476476
半区复制,用于新生代垃圾回收。将内存分为大小相同的两块,每次使用其中的一块。当这一块的内存使用完后,就将还存活的对象复制到另一块去,然后再把使用的空间一次清理掉。
477477

478-
![](https://raw.githubusercontent.com/Tyson0314/img/master/image-20210905003714551.png)
478+
![](http://img.dabin-coder.cn/image/image-20210905003714551.png)
479479

480480
特点:实现简单,运行高效,但可用内存缩小为了原来的一半,浪费空间。
481481

@@ -534,15 +534,15 @@ java -XX:+PrintCommandLineFlags -version
534534

535535
单线程收集器,使用一条垃圾收集线程去完成垃圾收集工作,在进行垃圾收集工作的时候必须暂停其他所有的工作线程( "Stop The World" ),直到它收集结束。
536536

537-
![](https://raw.githubusercontent.com/Tyson0314/img/master/serial-collector.png)
537+
![](http://img.dabin-coder.cn/image/serial-collector.png)
538538

539539
特点:简单高效;内存消耗最小;没有线程交互的开销,单线程收集效率高;需暂停所有的工作线程,用户体验不好。
540540

541541
### ParNew 收集器
542542

543543
Serial 收集器的多线程版本,除了使用多线程进行垃圾收集外,其余行为(控制参数、收集算法、回收策略等等)和 Serial 收集器完全一样。
544544

545-
![](https://raw.githubusercontent.com/Tyson0314/img/master/parnew-collector.png)
545+
![](http://img.dabin-coder.cn/image/parnew-collector.png)
546546

547547
除了 Serial 收集器外,只有它能与 CMS 收集器配合工作。
548548

@@ -582,7 +582,7 @@ Concurrent Mark Sweep 并发标记清除,目的是获取最短应用停顿时
582582
- 重新标记: 在并发标记期间对象的引用关系可能会变化,需要重新进行标记。此阶段也会stw,停顿时间一般会比初始标记阶段的时间稍长,远远比并发标记阶段时间短。
583583
- 并发清除:清除死亡对象,由于不需要移动存活对象,所以这个阶段也是可以与用户线程同时并发的。
584584

585-
![](https://raw.githubusercontent.com/Tyson0314/img/master/cms-collector.png)
585+
![](http://img.dabin-coder.cn/image/cms-collector.png)
586586

587587
由于在整个过程中耗时最长的并发标记和并发清除阶段中,垃圾收集器线程都可以与用户线程一起工作,所以从总体上来说,CMS收集器的内存回收过程是与用户线程一起并发执行的。
588588

@@ -607,7 +607,7 @@ G1垃圾收集器的目标是用在多核、大内存的机器上,在不同应
607607

608608
G1将整个堆分成相同大小的分区(Region),有四种不同类型的分区:Eden、Survivor、Old和Humongous(大对象)。分区的大小取值范围为1M到32M,都是2的幂次方。Region大小可以通过`-XX:G1HeapRegionSize`参数指定。Humongous区域用于存储大对象。G1认为只要大小超过了一个Region容量一半的对象即可判定为大对象。
609609

610-
![](https://raw.githubusercontent.com/Tyson0314/img/master/g1-region.jpg)
610+
![](http://img.dabin-coder.cn/image/g1-region.jpg)
611611

612612
G1 收集器对各个Region回收所获得的空间大小和回收所需时间的经验值进行排序,得到一个优先级列表,每次根据用户设置的最大的回收停顿时间(使用参数-XX:MaxGCPauseMillis指定,默认值是200毫秒),优先处理回收价值最大的 Region。
613613

Java/JVM高频面试题.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
JVM内存结构分为5大区域,**程序计数器****虚拟机栈****本地方法栈********方法区**
44

5-
![](https://raw.githubusercontent.com/Tyson0314/img/master/jvm内存结构0.png)
5+
![](http://img.dabin-coder.cn/image/jvm内存结构0.png)
66

77
### 程序计数器
88

@@ -138,7 +138,7 @@ ClassFile {
138138

139139
类的加载指的是将类的`class`文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个此类的对象,通过这个对象可以访问到方法区对应的类信息。
140140

141-
![](https://raw.githubusercontent.com/Tyson0314/img/master/类加载.png)
141+
![](http://img.dabin-coder.cn/image/类加载.png)
142142

143143
**加载**
144144

@@ -166,7 +166,7 @@ ClassFile {
166166

167167
一个类加载器收到一个类的加载请求时,它首先不会自己尝试去加载它,而是把这个请求**委派**给父类加载器去完成,这样层层委派,因此所有的加载请求最终都会传送到顶层的启动类加载器中,只有当父类加载器反馈自己无法完成这个加载请求时,子加载器才会尝试自己去加载。
168168

169-
![](https://raw.githubusercontent.com/Tyson0314/img/master/双亲委派.png)
169+
![](http://img.dabin-coder.cn/image/双亲委派.png)
170170

171171
双亲委派模型的具体实现代码在 `java.lang.ClassLoader`中,此类的 `loadClass()` 方法运行过程如下:先检查类是否已经加载过,如果没有则让父类加载器去加载。当父类加载器加载失败时抛出 `ClassNotFoundException`,此时尝试自己去加载。源码如下:
172172

@@ -265,7 +265,7 @@ public class ReferenceCount {
265265

266266
通过`GC Root`对象为起点,从这些节点向下搜索,搜索所走过的路径叫引用链,当一个对象到`GC Root`没有任何的引用链相连时,说明这个对象是不可用的。
267267

268-
![](https://raw.githubusercontent.com/Tyson0314/img/master/可达性分析0.png)
268+
![](http://img.dabin-coder.cn/image/可达性分析0.png)
269269

270270
## 可作为GC Roots的对象有哪些?
271271

@@ -366,7 +366,7 @@ GC(`Garbage Collection`),垃圾回收,是Java与C++的主要区别之一
366366

367367
首先利用可达性去遍历内存,把存活对象和垃圾对象进行标记。标记结束后统一将所有标记的对象回收掉。这种垃圾回收算法效率较低,并且会**产生大量不连续的空间碎片**
368368

369-
![](https://raw.githubusercontent.com/Tyson0314/img/master/标记清除.png)
369+
![](http://img.dabin-coder.cn/image/标记清除.png)
370370

371371
**复制清除算法**
372372

@@ -378,7 +378,7 @@ GC(`Garbage Collection`),垃圾回收,是Java与C++的主要区别之一
378378

379379
根据老年代的特点提出的一种标记算法,标记过程仍然与`标记-清除`算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉边界以外的内存。
380380

381-
![](https://raw.githubusercontent.com/Tyson0314/img/master/标记整理.png)
381+
![](http://img.dabin-coder.cn/image/标记整理.png)
382382

383383
**分类收集算法**
384384

@@ -461,7 +461,7 @@ G1垃圾收集器的目标是在不同应用场景中**追求高吞吐量和低
461461

462462
G1将整个堆分成相同大小的分区(`Region`),有四种不同类型的分区:`Eden、Survivor、Old和Humongous`。分区的大小取值范围为 1M 到 32M,都是2的幂次方。分区大小可以通过`-XX:G1HeapRegionSize`参数指定。`Humongous`区域用于存储大对象。G1规定只要大小超过了一个分区容量一半的对象就认为是大对象。
463463

464-
![](https://raw.githubusercontent.com/Tyson0314/img/master/g1分区.png)
464+
![](http://img.dabin-coder.cn/image/g1分区.png)
465465

466466
G1 收集器对各个分区回收所获得的空间大小和回收所需时间的经验值进行排序,得到一个优先级列表,每次根据用户设置的最大回收停顿时间,优先回收价值最大的分区。
467467

@@ -703,4 +703,4 @@ class Person {
703703

704704

705705

706-
![](https://raw.githubusercontent.com/Tyson0314/img/master/20220612101342.png)
706+
![](http://img.dabin-coder.cn/image/20220612101342.png)
File renamed without changes.

Java/Java基础.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -976,7 +976,7 @@ Class 类提供了一些方法,可以获取成员变量、成员方法、接
976976

977977
Field提供了类和接口中字段的信息,通过Field类可以动态访问这些字段。下图是Field类提供的一些方法。
978978

979-
![field-method](https://raw.githubusercontent.com/Tyson0314/img/master/field-method.png)
979+
![field-method](http://img.dabin-coder.cn/image/field-method.png)
980980

981981
## Method类
982982

@@ -1101,7 +1101,7 @@ public class GenericMethod {
11011101

11021102
Throwable类是Error和Exception的父类,只有继承于Throwable的类或者其子类才能被抛出。Throwable分为两类:
11031103

1104-
![exception](https://raw.githubusercontent.com/Tyson0314/img/master/exception.png)
1104+
![exception](http://img.dabin-coder.cn/image/exception.png)
11051105

11061106
- Error:JVM 无法解决的严重问题,如栈溢出(StackOverflowError)、内存溢出(OOM)等。程序无法处理的错误。
11071107

@@ -1198,7 +1198,7 @@ public class ExceptionTest {
11981198

11991199
Java IO流的核心就是对文件的操作,对于字节 、字符类型的输入和输出流。IO流主要分为两大类,字节流和字符流。字节流可以处理任何类型的数据,如图片,视频等,字符流只能处理字符类型的数据。
12001200

1201-
![io](https://raw.githubusercontent.com/Tyson0314/img/master/io.jpg)
1201+
![io](http://img.dabin-coder.cn/image/io.jpg)
12021202

12031203
> 图片参考:[Java io学习整理](https://zhuanlan.zhihu.com/p/25418336)
12041204
@@ -1251,13 +1251,13 @@ OutputStreamWriter:字符到字节的转换,可对读取到的字符数据
12511251

12521252
同步阻塞I/O模式,数据的读取写入必须阻塞在一个线程内等待其完成。
12531253

1254-
![bio](https://raw.githubusercontent.com/Tyson0314/img/master/bio.png)
1254+
![bio](http://img.dabin-coder.cn/image/bio.png)
12551255

12561256
## NIO
12571257

12581258
NIO是一种同步非阻塞的I/O模型,在Java 1.4 中引入了 NIO 框架,对应 java.nio 包,提供了 Channel , Selector,Buffer等抽象。
12591259

1260-
![nio](https://raw.githubusercontent.com/Tyson0314/img/master/nio.png)
1260+
![nio](http://img.dabin-coder.cn/image/nio.png)
12611261

12621262
NIO与IO区别:
12631263

Java/Java基础面试题.md

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646

4747
**JVM** :英文名称(Java Virtual Machine),就是我们耳熟能详的 Java 虚拟机。Java 能够跨平台运行的核心在于 JVM 。
4848

49-
![](https://raw.githubusercontent.com/Tyson0314/img/master/20220402230447.png)
49+
![](http://img.dabin-coder.cn/image/20220402230447.png)
5050

5151
所有的java程序会首先被编译为.class的类文件,这种类文件可以在虚拟机上执行。也就是说class文件并不直接与机器的操作系统交互,而是经过虚拟机间接与操作系统交互,由虚拟机将程序解释给本地系统执行。
5252

@@ -56,7 +56,7 @@
5656

5757
英文名称(Java Runtime Environment),就是Java 运行时环境。我们编写的Java程序必须要在JRE才能运行。它主要包含两个部分,JVM 和 Java 核心类库。
5858

59-
![](https://raw.githubusercontent.com/Tyson0314/img/master/20220401234008.png)
59+
![](http://img.dabin-coder.cn/image/20220401234008.png)
6060

6161
JRE是Java的运行环境,并不是一个开发环境,所以没有包含任何开发工具,如编译器和调试器等。
6262

@@ -86,7 +86,7 @@ JRE = JVM + Java 核心类库
8686

8787
JDK = JRE + Java工具 + 编译器 + 调试器
8888

89-
![](https://raw.githubusercontent.com/Tyson0314/img/master/20220402230613.png)
89+
![](http://img.dabin-coder.cn/image/20220402230613.png)
9090

9191
## 面向对象有哪些特性?
9292

@@ -232,7 +232,11 @@ private static class IntegerCache {
232232

233233
## String 为什么不可变?
234234

235-
先看下Java8 String类的源码:
235+
先看看什么是不可变的对象。
236+
237+
如果一个对象,在它创建完成之后,不能再改变它的状态,那么这个对象就是不可变的。不能改变状态的意思是,不能改变对象内的成员变量,包括基本数据类型的值不能改变,引用类型的变量不能指向其他的对象,引用类型指向的对象的状态也不能改变。
238+
239+
接着来看Java8 String类的源码:
236240

237241
```java
238242
public final class String
@@ -245,12 +249,27 @@ public final class String
245249
}
246250
```
247251

248-
String类是final的,它的所有成员变量也都是final的。为什么是final的?
252+
从源码可以看出,String对象其实在内部就是一个个字符,存储在这个value数组里面的。
253+
254+
value数组用final修饰,final 修饰的变量,值不能被修改。因此value不可以指向其他对象。
255+
256+
String类内部所有的字段都是私有的,也就是被private修饰。而且String没有对外提供修改内部状态的方法,因此value数组不能改变。
257+
258+
所以,String是不可变的。
259+
260+
那为什么String要设计成不可变的?
261+
262+
主要有以下几点原因:
249263

250264
1. **线程安全**。同一个字符串实例可以被多个线程共享,因为字符串不可变,本身就是线程安全的。
251265
2. **支持hash映射和缓存。**因为String的hash值经常会使用到,比如作为 Map 的键,不可变的特性使得 hash 值也不会变,不需要重新计算。
266+
3. **出于安全考虑**。网络地址URL、文件路径path、密码通常情况下都是以String类型保存,假若String不是固定不变的,将会引起各种安全隐患。比如将密码用String的类型保存,那么它将一直留在内存中,直到垃圾收集器把它清除。假如String类不是固定不变的,那么这个密码可能会被改变,导致出现安全隐患。
252267
3. **字符串常量池优化**。String对象创建之后,会缓存到字符串常量池中,下次需要创建同样的对象时,可以直接返回缓存的引用。
253268

269+
既然我们的String是不可变的,它内部还有很多substring, replace, replaceAll这些操作的方法。这些方法好像会改变String对象?怎么解释呢?
270+
271+
其实不是的,我们每次调用replace等方法,其实会在堆内存中创建了一个新的对象。然后其value数组引用指向不同的对象。
272+
254273
## String, StringBuffer 和 StringBuilder区别
255274

256275
**1. 可变性**
@@ -975,7 +994,7 @@ unchecked Exception:
975994

976995
不同的线程干专业的事情,最终每个线程都没空着,系统的吞吐量自然就上去了。
977996

978-
![](https://raw.githubusercontent.com/Tyson0314/img/master/20220423154450.png)
997+
![](http://img.dabin-coder.cn/image/20220423154450.png)
979998

980999

9811000

@@ -1113,4 +1132,4 @@ Java泛型是JDK 5中引⼊的⼀个新特性, 允许在定义类和接口的
11131132

11141133

11151134

1116-
![](https://raw.githubusercontent.com/Tyson0314/img/master/20220612101342.png)
1135+
![](http://img.dabin-coder.cn/image/20220612101342.png)

0 commit comments

Comments
 (0)