@@ -103,23 +103,21 @@ Java 虚拟机所管理的内存中最大的一块,Java 堆是所有线程共
103
103
104
104
Java 世界中“几乎”所有的对象都在堆中分配,但是,随着 JIT 编译器的发展与逃逸分析技术逐渐成熟,栈上分配、标量替换优化技术将会导致一些微妙的变化,所有的对象都分配到堆上也渐渐变得不那么“绝对”了。从 JDK 1.7 开始已经默认开启逃逸分析,如果某些方法中的对象引用没有被返回或者未被外面使用(也就是未逃逸出去),那么对象可以直接在栈上分配内存。
105
105
106
- Java 堆是垃圾收集器管理的主要区域,因此也被称作** GC 堆(Garbage Collected Heap)** 。从垃圾回收的角度,由于现在收集器基本都采用分代垃圾收集算法,所以 Java 堆还可以细分为:新生代和老年代;再细致一点有:Eden 空间、From Survivor、To Survivor 空间等 。** 进一步划分的目的是更好地回收内存,或者更快地分配内存。**
106
+ Java 堆是垃圾收集器管理的主要区域,因此也被称作** GC 堆(Garbage Collected Heap)** 。从垃圾回收的角度,由于现在收集器基本都采用分代垃圾收集算法,所以 Java 堆还可以细分为:新生代和老年代;再细致一点有:Eden、 Survivor、Old 等空间 。** 进一步划分的目的是更好地回收内存,或者更快地分配内存。**
107
107
108
108
在 JDK 7 版本及 JDK 7 版本之前,堆内存被通常分为下面三部分:
109
109
110
110
1 . 新生代内存(Young Generation)
111
111
2 . 老生代(Old Generation)
112
- 3 . 永生代 (Permanent Generation)
112
+ 3 . 永久代 (Permanent Generation)
113
113
114
- ![ JVM堆内存结构-JDK7 ] ( ./pictures/java内存区域/JVM堆内存结构-JDK7.png )
114
+ 下图所示的 Eden 区、两个 Survivor 区 S0 和 S1 都属于新生代,中间一层属于老年代,最下面一层属于永久代。
115
115
116
- JDK 8 版本之后方法区(HotSpot 的永久代)被彻底移除了(JDK1.7 就已经开始了),取而代之是元空间,元空间使用的是直接内存。
116
+ ![ hotspot-heap-structure ] ( ./pictures/java内存区域/hotspot-heap-structure.jpg )
117
117
118
- ![ JVM堆内存结构-JDK8 ] ( ./pictures/java内存区域/JVM堆内存结构-jdk8.png )
118
+ ** JDK 8 版本之后 PermGen 已被 Metaspace(元空间) 取代,元空间使用的是直接内存。 **
119
119
120
- ** 上图所示的 Eden 区、两个 Survivor 区都属于新生代(为了区分,这两个 Survivor 区域按照顺序被命名为 from 和 to),中间一层属于老年代。**
121
-
122
- 大部分情况,对象都会首先在 Eden 区域分配,在一次新生代垃圾回收后,如果对象还存活,则会进入 s0 或者 s1,并且对象的年龄还会加 1(Eden 区->Survivor 区后对象的初始年龄变为 1),当它的年龄增加到一定程度(默认为 15 岁),就会被晋升到老年代中。对象晋升到老年代的年龄阈值,可以通过参数 ` -XX:MaxTenuringThreshold ` 来设置。
120
+ 大部分情况,对象都会首先在 Eden 区域分配,在一次新生代垃圾回收后,如果对象还存活,则会进入 S0 或者 S1,并且对象的年龄还会加 1(Eden 区->Survivor 区后对象的初始年龄变为 1),当它的年龄增加到一定程度(默认为 15 岁),就会被晋升到老年代中。对象晋升到老年代的年龄阈值,可以通过参数 ` -XX:MaxTenuringThreshold ` 来设置。
123
121
124
122
> ** 🐛 修正(参见:[ issue552] ( https://github.com/Snailclimb/JavaGuide/issues/552 ) )** :“Hotspot 遍历所有对象时,按照年龄从小到大对其所占用的大小进行累积,当累积的某个年龄大小超过了 survivor 区的一半时,取这个年龄和 MaxTenuringThreshold 中更小的一个值,作为新的晋升年龄阈值”。
125
123
>
@@ -141,7 +139,7 @@ JDK 8 版本之后方法区(HotSpot 的永久代)被彻底移除了(JDK1.7
141
139
> }
142
140
> ```
143
141
144
- 堆这里最容易出现的就是 OutOfMemoryError 错误,并且出现这种错误之后的表现形式还会有几种,比如:
142
+ 堆这里最容易出现的就是 ` OutOfMemoryError` 错误,并且出现这种错误之后的表现形式还会有几种,比如:
145
143
146
144
1. **`java.lang.OutOfMemoryError: GC Overhead Limit Exceeded`** : 当 JVM 花太多时间执行垃圾回收并且只能回收很少的堆空间时,就会发生此错误。
147
145
2. **`java.lang.OutOfMemoryError: Java heap space`** :假如在创建新的对象时, 堆内存中的空间不足以存放新创建的对象, 就会引发此错误。(和配置的最大堆内存有关,且受制于物理内存大小。最大堆内存可通过`-Xmx`参数配置,若没有特别配置,将会使用默认值,详见:[Default Java 8 max heap size](https://stackoverflow.com/questions/28272923/default-xmxsize-in-java-8-max-heap-size))
0 commit comments