3131
3232# 一、运行时数据区域
3333
34- <div align =" center " > <img src =" pics/ab701824-e308-4284-88b6-596cc606fadb.png " width =" 450 " /> </div ><br >
34+ <div align =" center " > <img src =" pics/11548742157520.gif " width =" 450 " /> </div ><br >
3535
3636## 程序计数器
3737
4141
4242每个 Java 方法在执行的同时会创建一个栈帧用于存储局部变量表、操作数栈、常量池引用等信息。从方法调用直至执行完成的过程,就对应着一个栈帧在 Java 虚拟机栈中入栈和出栈的过程。
4343
44- <div align =" center " > <img src =" pics/28ab96b4-82ea-4d99-99fb-b320f60d0a58.png " width =" 500 " /> </div ><br >
44+ <div align =" center " > <img src =" pics/11548741556940.gif " width =" 500 " /> </div ><br >
4545
4646可以通过 -Xss 这个虚拟机参数来指定每个线程的 Java 虚拟机栈内存大小:
4747
@@ -60,7 +60,8 @@ java -Xss512M HackTheJava
6060
6161本地方法一般是用其它语言(C、C++ 或汇编语言等)编写的,并且被编译为基于本机硬件和操作系统的程序,对待这些方法需要特别处理。
6262
63- <div align =" center " > <img src =" pics/JNI-Java-Native-Interface.jpg " width =" 350 " /> </div ><br >
63+
64+ <div align =" center " > <img src =" pics/11548742010310.gif " /> </div ><br >
6465
6566## 堆
6667
@@ -140,7 +141,7 @@ Java 虚拟机使用该算法来判断对象是否可被回收,在 Java 中 GC
140141- 方法区中类静态属性引用的对象
141142- 方法区中的常量引用的对象
142143
143- <div align =" center " > <img src =" pics/0635cbe8.png " width = " " /> </div ><br >
144+ <div align =" center " > <img src =" pics/11548742505541.gif " /> </div ><br >
144145
145146### 3. 方法区的回收
146147
@@ -220,7 +221,7 @@ obj = null;
220221
221222### 1. 标记 - 清除
222223
223- <div align =" center " > <img src =" pics/a4248c4b-6c1d-4fb8-a557-86da92d3a294.jpg " width = " " /> </div ><br >
224+ <div align =" center " > <img src =" pics/11548743021625.gif " /> </div ><br >
224225
225226标记要回收的对象,然后清除。
226227
@@ -231,21 +232,21 @@ obj = null;
231232
232233### 2. 标记 - 整理
233234
234- <div align =" center " > <img src =" pics/902b83ab-8054-4bd2-898f-9a4a0fe52830.jpg " width = " " /> </div ><br >
235+ <div align =" center " > <img src =" pics/11548743193273.gif " /> </div ><br >
235236
236237让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存。
237238
238239### 3. 复制
239240
240- <div align =" center " > <img src =" pics/e6b733ad-606d-4028-b3e8-83c3a73a3797.jpg " width = " " /> </div ><br >
241+ <div align =" center " > <img src =" pics/11548743457272.gif " /> </div ><br >
241242
242243将内存划分为大小相等的两块,每次只使用其中一块,当这一块内存用完了就将还存活的对象复制到另一块上面,然后再把使用过的内存空间进行一次清理。
243244
244245主要不足是只使用了内存的一半。
245246
246- 现在的商业虚拟机都采用这种收集算法回收新生代,但是并不是划分为大小相等的两块,而是一块较大的 Eden 空间和两块较小的 Survivor 空间,每次使用 Eden 空间和其中一块 Survivor。在回收时,将 Eden 和 Survivor 中还存活着的对象全部复制到另一块 Survivor 空间上 ,最后清理 Eden 和使用过的那一块 Survivor。
247+ 现在的商业虚拟机都采用这种收集算法回收新生代,但是并不是划分为大小相等的两块,而是一块较大的 Eden 空间和两块较小的 Survivor 空间,每次使用 Eden 和其中一块 Survivor。在回收时,将 Eden 和 Survivor 中还存活着的对象全部复制到另一块 Survivor 上 ,最后清理 Eden 和使用过的那一块 Survivor。
247248
248- HotSpot 虚拟机的 Eden 和 Survivor 的大小比例默认为 8:1,保证了内存的利用率达到 90%。如果每次回收有多于 10% 的对象存活,那么一块 Survivor 空间就不够用了 ,此时需要依赖于老年代进行空间分配担保,也就是借用老年代的空间存储放不下的对象。
249+ HotSpot 虚拟机的 Eden 和 Survivor 大小比例默认为 8:1,保证了内存的利用率达到 90%。如果每次回收有多于 10% 的对象存活,那么一块 Survivor 就不够用了 ,此时需要依赖于老年代进行空间分配担保,也就是借用老年代的空间存储放不下的对象。
249250
250251### 4. 分代收集
251252
@@ -262,7 +263,7 @@ HotSpot 虚拟机的 Eden 和 Survivor 的大小比例默认为 8:1,保证了
262263
263264以上是 HotSpot 虚拟机中的 7 个垃圾收集器,连线表示垃圾收集器可以配合使用。
264265
265- - 单线程与多线程:单线程指的是垃圾收集器只使用一个线程进行收集 ,而多线程使用多个线程;
266+ - 单线程与多线程:单线程指的是垃圾收集器只使用一个线程 ,而多线程使用多个线程;
266267- 串行与并行:串行指的是垃圾收集器与用户程序交替执行,这意味着在执行垃圾收集的时候需要停顿用户程序;并行指的是垃圾收集器和用户程序同时执行。除了 CMS 和 G1 之外,其它垃圾收集器都是以串行的方式执行。
267268
268269### 1. Serial 收集器
@@ -275,7 +276,7 @@ Serial 翻译为串行,也就是说它以串行的方式执行。
275276
276277它的优点是简单高效,对于单个 CPU 环境来说,由于没有线程交互的开销,因此拥有最高的单线程收集效率。
277278
278- 它是 Client 模式下的默认新生代收集器,因为在该应用场景下内存一般来说不会很大。Serial 收集器收集几十兆甚至一两百兆的新生代停顿时间可以控制在一百多毫秒以内 ,只要不是太频繁,这点停顿是可以接受的 。
279+ 它是 Client 模式下的默认新生代收集器,因为在该应用场景下内存一般来说不会很大。它收集几十兆甚至一两百兆的新生代停顿时间可以控制在一百多毫秒以内 ,只要不是太频繁,这点停顿时间是可以接受的 。
279280
280281### 2. ParNew 收集器
281282
@@ -285,8 +286,6 @@ Serial 翻译为串行,也就是说它以串行的方式执行。
285286
286287是 Server 模式下首选的新生代收集器,除了性能原因外,主要是因为除了 Serial 收集器,只有它能与 CMS 收集器配合工作。
287288
288- 默认开启的线程数量与 CPU 数量相同,可以使用 -XX: ParallelGCThreads 参数来设置线程数。
289-
290289### 3. Parallel Scavenge 收集器
291290
292291与 ParNew 一样是多线程收集器。
@@ -441,7 +440,7 @@ G1 把堆划分成多个大小相等的独立区域(Region),新生代和
441440
442441## 类的生命周期
443442
444- <div align =" center " > <img src =" pics/32b8374a-e822-4720-af0b-c0f485095ea2.jpg " width = " " /> </div ><br >
443+ <div align =" center " > <img src =" pics/11548744140733.gif " /> </div ><br >
445444
446445包括以下 7 个阶段:
447446
@@ -583,17 +582,17 @@ System.out.println(ConstClass.HELLOWORLD);
583582
584583## 类与类加载器
585584
586- 两个类相等需要类本身相等 ,并且使用同一个类加载器进行加载。这是因为每一个类加载器都拥有一个独立的类名称空间。
585+ 两个类相等,需要类本身相等 ,并且使用同一个类加载器进行加载。这是因为每一个类加载器都拥有一个独立的类名称空间。
587586
588587这里的相等,包括类的 Class 对象的 equals() 方法、isAssignableFrom() 方法、isInstance() 方法的返回结果为 true,也包括使用 instanceof 关键字做对象所属关系判定结果为 true。
589588
590589## 类加载器分类
591590
592591从 Java 虚拟机的角度来讲,只存在以下两种不同的类加载器:
593592
594- - 启动类加载器(Bootstrap ClassLoader),这个类加载器用 C++ 实现,是虚拟机自身的一部分;
593+ - 启动类加载器(Bootstrap ClassLoader),使用 C++ 实现,是虚拟机自身的一部分;
595594
596- - 所有其他类的加载器,这些类由 Java 实现,独立于虚拟机外部,并且全都继承自抽象类 java.lang.ClassLoader。
595+ - 所有其它类的加载器,使用 Java 实现,独立于虚拟机,继承自抽象类 java.lang.ClassLoader。
597596
598597从 Java 开发人员的角度看,类加载器可以划分得更细致一些:
599598
@@ -607,13 +606,13 @@ System.out.println(ConstClass.HELLOWORLD);
607606
608607应用程序都是由三种类加载器相互配合进行加载的,如果有必要,还可以加入自己定义的类加载器。
609608
610- 下图展示的类加载器之间的层次关系,称为类加载器的双亲委派模型(Parents Delegation Model)。该模型要求除了顶层的启动类加载器外,其余的类加载器都应有自己的父类加载器 。这里类加载器之间的父子关系一般通过组合(Composition)关系来实现,而不是通过继承(Inheritance)的关系实现。
609+ 下图展示的类加载器之间的层次关系,称为类加载器的双亲委派模型(Parents Delegation Model)。该模型要求除了顶层的启动类加载器外,其余的类加载器都要有自己的父类加载器 。这里类加载器之间的父子关系一般通过组合(Composition)关系来实现,而不是通过继承(Inheritance)的关系实现。
611610
612611<div align =" center " > <img src =" pics/class_loader_hierarchy.png " width =" 600 " /> </div ><br >
613612
614613### 1. 工作过程
615614
616- 一个类加载器首先将类加载请求传送到父类加载器,只有当父类加载器无法完成类加载请求时才尝试加载 。
615+ 一个类加载器首先将类加载请求传送到父类加载器,只有当父类加载器无法完成类加载请求时才尝试自己加载 。
617616
618617### 2. 好处
619618
0 commit comments