Skip to content

Commit 65f26b3

Browse files
committed
update docs
1 parent 948232b commit 65f26b3

File tree

8 files changed

+52
-47
lines changed

8 files changed

+52
-47
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@
9292

9393
> [Java 虚拟机](docs/jvm) 记录了 JVM 的基本机制。
9494
95-
![img](http://dunwu.test.upcdn.net/snap/20200221180028.png)
95+
![img](http://dunwu.test.upcdn.net/snap/20200628154803.png)
9696

9797
- [JVM 体系结构](docs/jvm/jvm-architecture.md)
9898
- [JVM 内存区域](docs/jvm/jvm-memory.md) - 关键词:程序计数器、虚拟机栈、本地方法栈、堆、方法区、运行时常量池、直接内存、`OutOfMemoryError``StackOverflowError`

assets/javacore.xmind

5.48 KB
Binary file not shown.

docs/.vuepress/config.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,10 @@ module.exports = {
102102
}
103103
},
104104
plugins: [
105+
['@vuepress/active-header-links', {
106+
sidebarLinkSelector: '.sidebar-link',
107+
headerAnchorSelector: '.header-anchor'
108+
}],
105109
["@vuepress/back-to-top", true],
106110
[
107111
"@vuepress/pwa",

docs/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ footer: CC-BY-SA-4.0 Licensed | Copyright © 2018-Now Dunwu
9090

9191
> [Java 虚拟机](jvm) 记录了 JVM 的基本机制。
9292
93-
![img](http://dunwu.test.upcdn.net/snap/20200221180028.png)
93+
![img](http://dunwu.test.upcdn.net/snap/20200628154803.png)
9494

9595
- [JVM 体系结构](jvm/jvm-architecture.md)
9696
- [JVM 内存区域](jvm/jvm-memory.md) - 关键词:程序计数器、虚拟机栈、本地方法栈、堆、方法区、运行时常量池、直接内存、`OutOfMemoryError``StackOverflowError`

docs/concurrent/java-concurrent-basic-mechanism.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -731,7 +731,7 @@ public class ThreadLocalDemo {
731731

732732
#### 内存泄漏问题
733733

734-
ThreadLocalMap 的 `Entry` 继承了 `WeakReference`,所以它的 key (`ThreadLocal` 对象)是弱引用,而 value (变量副本)是强引用。
734+
`ThreadLocalMap``Entry` 继承了 `WeakReference`,所以它的 key (`ThreadLocal` 对象)是弱引用,而 value (变量副本)是强引用。
735735

736736
- 如果 `ThreadLocal` 对象没有外部强引用来引用它,那么 `ThreadLocal` 对象会在下次 GC 时被回收。
737737
- 此时,`Entry` 中的 key 已经被回收,但是 value 由于是强引用不会被垃圾收集器回收。如果创建 `ThreadLocal` 的线程一直持续运行,那么 value 就会一直得不到回收,产生内存泄露。

docs/jvm/jvm-gc.md

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -56,19 +56,18 @@ public class ReferenceCountingGC {
5656

5757
### 可达性分析算法
5858

59-
通过 GC Roots 作为起始点进行搜索,能够到达到的对象都是存活的,不可达的对象可被回收
59+
通过 **GC Roots** 作为起始点进行搜索,JVM 将能够到达到的对象视为**存活**,不可达的对象视为**死亡**
6060

6161
<div align="center">
6262
<img src="http://dunwu.test.upcdn.net/cs/java/javacore/jvm/jvm-gc-root.png" />
6363
<p>可达性分析算法</p>
6464
</div>
65-
66-
Java 虚拟机使用该算法来判断对象是否可被回收,在 Java 中 GC Roots 一般包含以下内容:
65+
**可作为 GC Roots 的对象**包括下面几种:
6766

6867
- 虚拟机栈中引用的对象
69-
- 本地方法栈中引用的对象
70-
- 方法区中类静态属性引用的对象
71-
- 方法区中的常量引用的对象
68+
- 本地方法栈中引用的对象(Native 方法)
69+
- 方法区中,类静态属性引用的对象
70+
- 方法区中,常量引用的对象
7271

7372
### 引用类型
7473

@@ -291,7 +290,7 @@ JVM 会随意选取一个 `Survivor` 区域作为`to`,然后会在 GC 过程
291290

292291
串行收集器是 **`client` 模式下的默认收集器配置**。因为在客户端模式下,分配给虚拟机管理的内存一般来说不会很大。Serial 收集器收集几十兆甚至一两百兆的年轻代停顿时间可以控制在一百多毫秒以内,只要不是太频繁,这点停顿是可以接受的。
293292

294-
串行收集器采用单线程 **stop-the-world** 的方式进行收集。当内存不足时,串行 GC 设置停顿标识,待所有线程都进入安全点(Safepoint)时,应用线程暂停,串行 GC 开始工作,**采用单线程方式回收空间并整理内存**
293+
**串行收集器采用单线程 stop-the-world 的方式进行收集**。当内存不足时,串行 GC 设置停顿标识,待所有线程都进入安全点(Safepoint)时,应用线程暂停,串行 GC 开始工作,**采用单线程方式回收空间并整理内存**
295294

296295
<div align="center">
297296
<img src="http://dunwu.test.upcdn.net/cs/java/javacore/jvm/jvm-gc-serial.jpg" />
@@ -610,17 +609,22 @@ G1 选择活性最低的区域,这些区域能够以最快的速度回收。
610609

611610
### Minor GC
612611

613-
Minor GC 发生在年轻代上,因为年轻代对象存活时间很短,因此 Minor GC 会频繁执行,执行的速度一般也会比较快。
612+
**`Eden` 区空间不足时,触发 Minor GC**
613+
614+
**Minor GC 发生在年轻代上**,因为年轻代对象存活时间很短,因此 Minor GC 会频繁执行,执行的速度一般也会比较快。
615+
616+
Minor GC 工作流程:
614617

615-
(1)Java 应用不断创建对象,通常都是分配在 Eden 区域,当其空间占用达到一定阈值时,触发 minor GC。仍然被引用的对象(绿色方块)存活下来,被复制到 JVM 选择的 Survivor 区域,而没有被引用的对象(黄色方块)则被回收。
618+
1. Java 应用不断创建对象,通常都是分配在 `Eden` 区域,当其空间不足时(达到设定的阈值),触发 minor GC。仍然被引用的对象(绿色方块)存活下来,被复制到 JVM 选择的 Survivor 区域,而没有被引用的对象(黄色方块)则被回收。
616619

617-
(2)经过一次 Minor GC,Eden 就会空闲下来,直到再次达到 Minor GC 触发条件。这时候,另外一个 Survivor 区域则会成为 to 区域,Eden 区域的存活对象和 From 区域对象,都会被复制到 to 区域,并且存活的年龄计数会被加 1。
620+
2. 经过一次 Minor GC,Eden 就会空闲下来,直到再次达到 Minor GC 触发条件。这时候,另外一个 Survivor 区域则会成为 `To` 区域,Eden 区域的存活对象和 `From` 区域对象,都会被复制到 `To` 区域,并且存活的年龄计数会被加 1。
621+
622+
3. 类似第二步的过程会发生很多次,直到有对象年龄计数达到阈值,这时候就会发生所谓的晋升(Promotion)过程,如下图所示,超过阈值的对象会被晋升到老年代。这个阈值是可以通过 `-XX:MaxTenuringThreshold` 参数指定。
618623

619-
(3)类似第二步的过程会发生很多次,直到有对象年龄计数达到阈值,这时候就会发生所谓的晋升(Promotion)过程,如下图所示,超过阈值的对象会被晋升到老年代。这个阈值是可以通过 `-XX:MaxTenuringThreshold` 参数指定。
620624

621625
### Full GC
622626

623-
Full GC 发生在老年代上,老年代对象和年轻代的相反,其存活时间长,因此 Full GC 很少执行,而且执行速度会比 Minor GC 慢很多。
627+
**Full GC 发生在老年代上**,老年代对象和年轻代的相反,其存活时间长,因此 Full GC 很少执行,而且执行速度会比 Minor GC 慢很多。
624628

625629
#### 内存分配策略
626630

@@ -660,25 +664,24 @@ Full GC 发生在老年代上,老年代对象和年轻代的相反,其存活
660664

661665
**(2)老年代空间不足**
662666

663-
老年代空间不足的常见场景为前文所讲的大对象直接进入老年代、长期存活的对象进入老年代等,当执行 Full GC 后空间仍然不足,则抛出 `Java.lang.OutOfMemoryError`。为避免以上原因引起的 Full GC,调优时应尽量做到让对象在 Minor GC 阶段被回收、让对象在年轻代多存活一段时间以及不要创建过大的对象及数组。
667+
老年代空间不足的常见场景为前文所讲的大对象直接进入老年代、长期存活的对象进入老年代等,当执行 Full GC 后空间仍然不足,则抛出 `java.lang.OutOfMemoryError: Java heap space`。为避免以上原因引起的 Full GC,调优时应尽量做到让对象在 Minor GC 阶段被回收、让对象在年轻代多存活一段时间以及不要创建过大的对象及数组。
664668

665-
**(3)空间分配担保失败**
669+
**(3)方法区空间不足**
666670

667-
使用复制算法的 Minor GC 需要老年代的内存空间作担保,如果出现了 `HandlePromotionFailure` 担保失败,则会触发 Full GC。
671+
JVM 规范中运行时数据区域中的**方法区**,在 HotSpot 虚拟机中又被习惯称为**永久代**,永久代中存放的是类的描述信息、常量、静态变量等数据,当系统中要加载的类、反射的类和调用的方法较多时,永久代可能会被占满,在未配置为采用 CMS GC 的情况下也会执行 Full GC。如果经过 Full GC 仍然回收不了,那么 JVM 会抛出 `java.lang.OutOfMemoryError: PermGen space` 错误。为避免永久代占满造成 Full GC 现象,可采用的方法为增大 Perm Gen 空间或转为使用 CMS GC。
668672

669-
**(4)JDK 1.7 及以前的永久代空间不足**
673+
**(4)Minor GC 的平均晋升空间大小大于老年代可用空间**
670674

671-
在 JDK 1.7 及以前,HotSpot 虚拟机中的方法区是用永久代实现的,永久代中存放的为一些 Class 的信息、常量、静态变量等数据,当系统中要加载的类、反射的类和调用的方法较多时,永久代可能会被占满,在未配置为采用 CMS GC 的情况下也会执行 Full GC。如果经过 Full GC 仍然回收不了,那么虚拟机会抛出 `java.lang.OutOfMemoryError`,为避免以上原因引起的 Full GC,可采用的方法为增大永久代空间或转为使用 CMS GC。
675+
如果发现统计数据说之前 Minor GC 的平均晋升大小比目前老年代剩余的空间大,则不会触发 Minor GC 而是转为触发 Full GC。
672676

673-
**五)Concurrent Mode Failure**
677+
**5)对象大小大于 To 区和老年代的可用内存**
674678

675-
执行 CMS GC 的过程中同时有对象要放入老年代,而此时老年代空间不足(有时候“空间不足”是 CMS GC 时当前的浮动垃圾过多导致暂时性的空间不足触发 Full GC),便会报 Concurrent Mode Failure 错误,并触发 Full GC
679+
`Eden` 区、`From` 区向 `To` 区复制时,对象大小大于 To 区可用内存,则把该对象转存到老年代,且老年代的可用内存小于该对象大小
676680

677681
## 参考资料
678682

679683
- [《深入理解 Java 虚拟机》](https://item.jd.com/11252778.html)
680684
- [从表到里学习 JVM 实现](https://www.douban.com/doulist/2545443/)
681685
- [详解 JVM Garbage First(G1) 垃圾收集器](https://blog.csdn.net/coderlius/article/details/79272773)
682686
- [G1 垃圾收集器入门](https://blog.csdn.net/zhanggang807/article/details/45956325)
683-
- [详解 JVM Garbage First(G1) 垃圾收集器](https://blog.csdn.net/coderlius/article/details/79272773)
684687
- [Getting Started with the G1 Garbage Collector](https://www.oracle.com/webfolder/technetwork/tutorials/obe/java/G1GettingStarted/index.html)

docs/jvm/jvm-memory.md

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,11 @@
1919
- [Java 内存区域对比](#java-内存区域对比)
2020
- [三、OutOfMemoryError](#三outofmemoryerror)
2121
- [什么是 OutOfMemoryError](#什么是-outofmemoryerror)
22-
- [Java heap space](#java-heap-space)
23-
- [GC overhead limit exceeded](#gc-overhead-limit-exceeded)
24-
- [PermGen space](#permgen-space)
25-
- [Metaspace](#metaspace)
26-
- [Unable to create new native thread](#unable-to-create-new-native-thread)
22+
- [堆空间溢出](#堆空间溢出)
23+
- [GC 开销超过限制](#gc-开销超过限制)
24+
- [永久代空间不足](#永久代空间不足)
25+
- [元数据区空间不足](#元数据区空间不足)
26+
- [无法新建本地线程](#无法新建本地线程)
2727
- [直接内存溢出](#直接内存溢出)
2828
- [四、StackOverflowError](#四stackoverflowerror)
2929
- [参考资料](#参考资料)
@@ -179,7 +179,7 @@ Java 堆是垃圾收集的主要区域(因此也被叫做"GC 堆")。现代
179179
180180
下面逐一介绍 OOM 发生场景。
181181
182-
### Java heap space
182+
### 堆空间溢出
183183
184184
`java.lang.OutOfMemoryError: Java heap space` 这个错误意味着:**堆空间溢出**
185185
@@ -277,7 +277,7 @@ public class HeapOutOfMemoryDemo {
277277
278278
但如果在现实中,代码并没有问题,仅仅是因为堆内存不足,可以通过 `-Xms` 和 `-Xmx` 适当调整堆内存大小。
279279
280-
### GC overhead limit exceeded
280+
### GC 开销超过限制
281281
282282
`java.lang.OutOfMemoryError: GC overhead limit exceeded` 这个错误,官方给出的定义是:**超过 `98%` 的时间用来做 GC 并且回收了不到 `2%` 的堆内存时会抛出此异常**。这意味着,发生在 GC 占用大量时间为释放很小空间的时候发生的,是一种保护机制。导致异常的原因:一般是因为堆太小,没有足够的内存。
283283
@@ -308,7 +308,7 @@ public class GcOverheadLimitExceededDemo {
308308
309309
**Java heap space** 错误处理方法类似,先判断是否存在内存泄漏。如果有,则修正代码;如果没有,则通过 `-Xms` 和 `-Xmx` 适当调整堆内存大小。
310310
311-
### PermGen space
311+
### 永久代空间不足
312312
313313
【错误】
314314
@@ -425,7 +425,7 @@ jmap -dump:file=dump.hprof,format=b <process-id>
425425
426426
然后,对于每个可疑者,就需要你手动将根本原因追溯到生成此类的应用程序代码。
427427
428-
### Metaspace
428+
### 元数据区空间不足
429429
430430
【错误】
431431
@@ -480,7 +480,7 @@ public class MethodAreaOutOfMemoryDemo {
480480
481481
另一种解决方案甚至更简单。你可以通过删除此参数来完全解除对 Metaspace 大小的限制,JVM 默认对 Metaspace 的大小没有限制。但是请注意以下事实:这样做可能会导致大量交换或达到本机物理内存而分配失败。
482482
483-
### Unable to create new native thread
483+
### 无法新建本地线程
484484
485485
`java.lang.OutOfMemoryError: Unable to create new native thread` 这个错误意味着:**Java 应用程序已达到其可以启动线程数的限制**。
486486
@@ -552,7 +552,7 @@ max user processes (-u) 1800
552552
553553
由直接内存导致的内存溢出,一个明显的特征是在 Head Dump 文件中不会看见明显的异常,如果发现 OOM 之后 Dump 文件很小,而程序中又直接或间接使用了 NIO,就可以考虑检查一下是不是这方面的原因。
554554
555-
示例:直接内存 `OutOfMemoryError`
555+
【示例】直接内存 `OutOfMemoryError`
556556
557557
```java
558558
/**
@@ -585,7 +585,7 @@ public class DirectOutOfMemoryDemo {
585585
- **递归函数调用层数太深**
586586
- **大量循环或死循环**
587587
588-
示例:递归函数调用层数太深导致 `StackOverflowError`
588+
【示例】递归函数调用层数太深导致 `StackOverflowError`
589589
590590
```java
591591
public class StackOverflowDemo {
@@ -616,5 +616,4 @@ public class StackOverflowDemo {
616616
- [从表到里学习 JVM 实现](https://www.douban.com/doulist/2545443/)
617617
- [作为测试你应该知道的 JAVA OOM 及定位分析](https://www.jianshu.com/p/28935cbfbae0)
618618
- [异常、堆内存溢出、OOM 的几种情况](https://blog.csdn.net/sinat_29912455/article/details/51125748)
619-
- [介绍JVMOOM8种类型](https://tianmingxing.com/2019/11/17/%E4%BB%8B%E7%BB%8DJVM%E4%B8%ADOOM%E7%9A%848%E7%A7%8D%E7%B1%BB%E5%9E%8B/)
620-
619+
- [介绍 JVMOOM8 种类型](https://tianmingxing.com/2019/11/17/%E4%BB%8B%E7%BB%8DJVM%E4%B8%ADOOM%E7%9A%848%E7%A7%8D%E7%B1%BB%E5%9E%8B/)

docs/package.json

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,23 @@
55
"scripts": {
66
"clean": "rimraf dist && rimraf .temp",
77
"build": "npm run clean && vuepress build ./ --temp .temp",
8-
"dev": "vuepress dev ./ --temp .temp",
8+
"start": "vuepress dev ./ --temp .temp",
99
"lint": "markdownlint -r markdownlint-rule-emphasis-style -c ./.markdownlint.json **/*.md -i node_modules",
1010
"lint:fix": "markdownlint -f -r markdownlint-rule-emphasis-style -c ./.markdownlint.json **/*.md -i node_modules",
1111
"show-help": "vuepress --help",
12-
"view-info": "vuepress view-info ./ --temp .temp",
13-
"deploy": "gh-pages -d dist"
12+
"view-info": "vuepress view-info ./ --temp .temp"
1413
},
1514
"devDependencies": {
16-
"@vuepress/plugin-back-to-top": "^1.3.0",
17-
"@vuepress/plugin-medium-zoom": "^1.3.0",
18-
"@vuepress/plugin-pwa": "^1.3.0",
19-
"@vuepress/theme-vue": "^1.3.0",
20-
"gh-pages": "^2.2.0",
21-
"markdownlint-cli": "^0.22.0",
15+
"@vuepress/plugin-active-header-links": "^1.5.2",
16+
"@vuepress/plugin-back-to-top": "^1.5.0",
17+
"@vuepress/plugin-medium-zoom": "^1.5.0",
18+
"@vuepress/plugin-pwa": "^1.5.0",
19+
"@vuepress/theme-vue": "^1.5.0",
20+
"markdownlint-cli": "^0.23.1",
2221
"markdownlint-rule-emphasis-style": "^1.0.1",
2322
"rimraf": "^3.0.1",
2423
"vue-toasted": "^1.1.25",
25-
"vuepress": "^1.3.0",
24+
"vuepress": "^1.5.0",
2625
"vuepress-plugin-flowchart": "^1.4.2"
2726
}
2827
}

0 commit comments

Comments
 (0)