@@ -12581,16 +12581,22 @@ Java**反编译**指令:`javap -v Test.class`
1258112581
1258212582#### 虚拟机栈
1258312583
12584- Java 虚拟机栈:Java Virtual Machine Stacks ,每个线程运行时所需要的内存
12584+ Java 虚拟机栈:Java Virtual Machine Stacks ,** 每个线程 ** 运行时所需要的内存
1258512585
1258612586* 虚拟机栈时线程私有的,对应方法调用到执行完成的整个过程
12587- * 保存执行方法时的** 局部变量、动态连接信息、方法返回地址信息** 等
12587+
12588+ * 保存执行方法时的** 局部变量表、常量池引用、方法返回地址信息** 等
12589+
1258812590* 每个栈由多个栈帧(Frame )组成,对应着每次方法调用时所占用的内存
12591+
1258912592* 每个线程只能有一个活动栈帧,对应着当前正在执行的那个方法
1259012593
12594+ < img src= " https://gitee.com/seazean/images/raw/master/JavaSE/JVM-虚拟机栈.png" style= " zoom:50%;" / >
12595+
1259112596设置栈内存大小:`- Xss size` `- Xss 1024k`
1259212597
1259312598* 进入 Run / Debug Configurations -- - > VM options 设置参数
12599+ * 在 JDK 1.4 中默认为 256K,而在 JDK 1.5 + 默认为 1M
1259412600
1259512601虚拟机栈特点:
1259612602
@@ -12602,10 +12608,10 @@ Java 虚拟机栈:Java Virtual Machine Stacks,每个线程运行时所需要
1260212608 * 如果方法内局部变量没有逃离方法的作用访问,它是线程安全的
1260312609 * 如果是局部变量引用了对象,并逃离方法的作用范围,需要考虑线程安全
1260412610
12605- 栈内存溢出 :
12611+ 异常 :
1260612612
12607- * 栈帧过多导致栈内存溢出 (超过了栈的容量)
12608- * 栈帧过大导致栈内存溢出
12613+ * 栈帧过多导致栈内存溢出 (超过了栈的容量),会抛出 OutOfMemoryError 异常
12614+ * 当线程请求的栈深度超过最大值,会抛出 StackOverflowError 异常
1260912615
1261012616线程运行诊断:
1261112617
@@ -12624,7 +12630,9 @@ Java 虚拟机栈:Java Virtual Machine Stacks,每个线程运行时所需要
1262412630
1262512631* 不需要进行GC ,与虚拟机栈类似
1262612632
12627- * 本地方法一般是由其他语言编写
12633+ * 本地方法一般是由其他语言编写,并且被编译为基于本机硬件和操作系统的程序,对这些方法需要特别处理
12634+
12635+ < img src= " https://gitee.com/seazean/images/raw/master/JavaSE/JVM-本地方法栈.png" style= " zoom:67%;" / >
1262812636
1262912637
1263012638
@@ -12636,7 +12644,7 @@ Java 虚拟机栈:Java Virtual Machine Stacks,每个线程运行时所需要
1263612644
1263712645Program Counter Register 程序计数器(寄存器)
1263812646
12639- 作用:内部保存字节码的行号,用于记录正在执行的字节码指令地址(下一条jvm指令的地址 )
12647+ 作用:内部保存字节码的行号,用于记录正在执行的字节码指令地址(如果正在执行的是本地方法则为空 )
1264012648
1264112649原理:
1264212650
@@ -12669,16 +12677,16 @@ Program Counter Register 程序计数器(寄存器)
1266912677
1267012678#### 堆
1267112679
12672- Heap 堆:主要用来保存** 对象实例,数组** 等,通过 new 关键字创建对象都会使用堆内存
12680+ Heap 堆:用来保存** 对象实例,数组** 等,通过 new 创建对象都会使用堆内存,是垃圾收集的主要区域("GC 堆")
12681+
1267312682特点:
1267412683
1267512684* 它是线程共享的,堆中对象都需要考虑线程安全的问题
1267612685* 有垃圾回收机制
12677- * 当堆中没有内存空间可分配给实例,也无法再扩展时,则抛出OutOfMemoryError异常
1267812686
1267912687设置堆内存指令:`-Xmx Size`
1268012688
12681- 内存溢出:new出对象,循环添加字符数据
12689+ 内存溢出:new出对象,循环添加字符数据,当堆中没有内存空间可分配给实例,也无法再扩展时,就会抛出OutOfMemoryError异常
1268212690
1268312691堆内存诊断工具:(控制台命令)
1268412692
@@ -12704,13 +12712,30 @@ public static void main(String[] args) throws InterruptedException {
1270412712
1270512713* Young 区被划分为三部分,Eden 区和两个大小严格相同的Survivor 区。Survivor 区间,某一时刻只有其中一个是被使用的,另外一个留做垃圾回收时复制对象。在Eden 区变满的时候, GC 就会将存活的对象移到空闲的Survivor 区间中,根据JVM 的策略,在经过几次垃圾回收后,仍然存活于Survivor 的对象将被移动到Tenured 区间
1270612714* Tenured 区主要保存生命周期长的对象,一般是一些老的对象,当一些对象在Young 复制转移一定的次数以后,对象就会被转移到Tenured 区
12707- * Perm 代主要保存** Class 、ClassLoader 、静态变量、常量、编译后的代码** ,在java7中堆内方法区会受到GC 的管理。方法区(永久代)有大小的限制,如果大量的动态生成类,放入到方法区,很容易造成OOM
12715+ * Perm 代主要保存** Class 、ClassLoader 、静态变量、常量、编译后的代码** ,在java7中堆内方法区会受到GC 的管理。
12716+
12717+
12718+
12719+ ***
12720+
12721+
12722+
12723+ #### 方法区
1270812724
12709- Java8 :
12725+ 方法区 / 永久代:在 HotSpot JVM 中,用于存放已被加载的类信息、常量池、静态变量以及即时编译器编译后的代码等数据,每当一个类初次被加载时,它的 ** 元数据 ** 都会放到永久代中
1271012726
12711- * 为了 ** 避免方法区出现 OOM ** ,在java8中将堆内的方法区(永久代)移动到了本地内存上,重新开辟了一块空间,叫做 ** 元空间 **
12727+ 方法区是一个 JVM 规范, ** 永久代与元空间都是其一种实现方式 **
1271212728
12729+ 方法区和堆一样不需要连续的内存,并且可以动态扩展;方法区有大小限制,因此加载的类太多,可能导致永久代内存溢出 (OutOfMemoryError );对这块区域进行垃圾回收主要是对常量池的回收和对类的卸载,比较难实现
1271312730
12731+ 为了** 避免方法区出现OOM ** ,在JDK8 中将堆内的方法区(永久代)移动到了本地内存上,重新开辟了一块空间,叫做** 元空间** ,元空间存储类的元信息,静态变量和常量池等放入堆中
12732+
12733+
12734+
12735+ ** 运行时常量池** 是方法区的一部分
12736+
12737+ * Class 文件中的常量池(编译器生成的字面量和符号引用)会在类加载后被放入这个区域
12738+ * 除了在编译期生成的常量,还允许动态生成,例如 String 类的 intern()
1271412739
1271512740
1271612741
@@ -12735,20 +12760,15 @@ Java8:
1273512760
1273612761
1273712762
12763+ ***
1273812764
1273912765
12740- ##### 元空间
12741-
12742- 在 HotSpot JVM 中,永久代( ≈ 方法区)中用于存放类和方法的元数据以及常量池,每当一个类初次被加载的时候,它的元数据都会放到永久代中。永久代是有大小限制的,因此加载的类太多,很可能导致永久代内存溢出,即OutOfMemoryError
12743-
12744- Java 8 中 PermGen 被移出 HotSpot JVM :
1274512766
12746- * 由于 PermGen 内存经常会溢出,引发OutOfMemoryError ,为了让这一块内存可以更灵活地被管理,不要经常出现OOM
12747- * 移除 PermGen 可以促进 HotSpot JVM 与 JRockit VM 的融合,因为 JRockit 没有永久代
12767+ ##### 元空间
1274812768
12749- PermGen 被元空间代替,其他内容比如** 类元信息 、字段、静态属性、方法、常量池** 等都移动到元空间区,元空间的本质和永久代类似,都是对 JVM 规范中方法区的实现
12769+ PermGen 被元空间代替,其他内容比如** 类信息 、字段、静态属性、方法、常量池** 等都移动到元空间区,元空间的本质和永久代类似,都是对 JVM 规范中方法区的实现
1275012770
12751- 元空间与永久代区别:元空间并不在虚拟机中,而是使用本地内存。因此默认情况下 ,元空间的大小仅受本地内存限制
12771+ 元空间与永久代区别:元空间不在虚拟机中,使用的本地内存,默认情况下 ,元空间的大小仅受本地内存限制
1275212772
1275312773方法区内存溢出:
1275412774
@@ -12795,7 +12815,7 @@ public class Demo1_8 extends ClassLoader { // 可以用来加载类的二进制
1279512815
1279612816
1279712817
12798-
12818+ ***
1279912819
1280012820
1280112821
@@ -12810,9 +12830,9 @@ Direct Memory特点:
1281012830分配和回收原理:
1281112831
1281212832* 使用了 Unsafe 对象完成直接内存的分配回收,并且回收需要主动调用 freeMemory 方法
12813- * ByteBuffer 的实现类内部,使用了 Cleaner (虚引用)来监测 ByteBuffer 对象,一旦
12814- * ByteBuffer 对象被垃圾回收,那么就会由 ReferenceHandler 线程通过 Cleaner 的 clean 方法调
12815- 用 freeMemory 来释放直接内存
12833+ * ByteBuffer 的实现类内部,使用了 Cleaner (虚引用)来监测 ByteBuffer 对象,一旦 ByteBuffer 对象被垃圾回收,那么就会由 ReferenceHandler 线程通过 Cleaner 的 clean 方法调用 freeMemory 来释放直接内存
12834+
12835+ < img src = " https://gitee.com/seazean/images/raw/master/JavaSE/JVM-直接内存.png " style = " zoom:50%; " / >
1281612836
1281712837```java
1281812838/**
@@ -12867,6 +12887,7 @@ public class Demo1_27 {
1286712887| - XX : + PrintFlagsFinal | 查看所有的参数的最终值< br / > (可能会存在修改,不再是初始值) |
1286812888| - XX : + PrintGCDetails | GC 详情,打印gc简要信息:< br / > 1. - XX :+ PrintGC 2. - verbose: gc |
1286912889| - XX : + ScavengeBeforeFullGC | FullGC 前 MinorGC |
12890+ | - XX : + DisableExplicitGC | 禁用显式垃圾回收,让System . gc无效 |
1287012891
1287112892
1287212893
0 commit comments