《JVM-概述-内存区域-回收算法-收集器》
一、JVM概述
JVM是Java Virtual Machine(Java虚拟机)的缩写。JVM 是运行在操作系统之上的,它与硬件没有直接的交互。
Java源文件 -> 编译器 -> 字节码文件 -> 字节码文件 -> JVM -> 机器码。
二、JVM内存区域主要分为
线程私有区域【程序计数器、虚拟机栈、本地方法区】
线程共享区域【JAVA堆、方法区】
- 程序计数器(线程私有)
一块较小的内存空间, 是当前线程所执行的字节码的行号指示器,每条线程都要有一个独立的程序计数器,这类内存也称为“线程私有”的内存。
正在执行java 方法的话,计数器记录的是虚拟机字节码指令的地址(当前指令的地址)。如果还是Native 方法,则为空。这个内存区域是唯一一个在虚拟机中没有规定任何OutOfMemoryError 情况的区域。
2. 虚拟机栈(线程私有)
是描述java 方法执行的内存模型,每个方法在执行的同时都会创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态链接、方法出口等信息。
每一个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。
3. 本地方法区(线程私有)
本地方法区和Java Stack 作用类似, 区别是虚拟机栈为执行Java 方法服务, 而本地方法栈则为Native 方法服务。
4. 堆(Heap-线程共享)-运行时数据区
是被线程共享的一块内存区域,创建的对象和数组都保存在Java 堆内存中,也是垃圾收集器进行垃圾收集的最重要的内存区域。
由于现代JVM 采用分代收集算法, 因此Java 堆从GC 的角度还可以细分为: 新生代(Eden 区、From Survivor 区和To Survivor 区)和老年代。
5. 方法区/永久代(线程共享)
永久代(Permanent Generation), 用于存储被JVM 加载的类信息、常量、静态变量、即时编译器编译后的代码等数据.
运行时常量池(Runtime Constant Pool)是方法区的一部分。
信息是常量池(Constant Pool Table),用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后存放到方法区的运行时常量池中。
三、JVM运行时内存
包含: 新生代(Eden 区、From Survivor 区和To Survivor 区)和老年代。
1. 新生代
新生代是用来存放新生的对象。一般占据堆的1/3 空间。由于频繁创建对象,所以新生代会频繁触发MinorGC 进行垃圾回收。
1) Eden 区
Java 新对象的出生地(如果新创建的对象占用内存很大,则直接分配到老年代)
2) ServivorFrom
上一次GC的幸存者,作为这一次GC的被扫描者。
3) ServivorTo
保留了一次MinorGC 过程中的幸存者。
MinorGC 的过程(复制->清空->互换),MinorGC 采用复制算法。
1) Eden、ServicorFrom 复制到 To Servicor,年龄+1 (默认情况下年龄到达15的对象会被移到老生代中)
2) 清空 Eden、From Servicor
3) To Servicor 和From Servicor 互换
2. 老年代
主要存放应用程序中生命周期长的内存对象。
老年代的对象比较稳定,所以MajorGC 不会频繁执行。
MajorGC 采用标记清除算法 : 首先扫描一次所有老年代,标记出存活的对象,然后回收没有标记的对象。
MajorGC 的耗时比较长,因为要扫描再回收。MajorGC 会产生内存碎片。
当老年代也满了装不下的时候,就会抛出OOM(Out of Memory)异常。
3. 永久代
指内存的永久保存区域,主要存放Class 和Meta(元数据)的信息,Class 在被加载的时候被放入永久区域。
JAVA8 与元数据
在Java8 中,永久代已经被移除,被一个称为“元数据区”(元空间)的区域所取代。
元空间的本质和永久代类似,元空间与永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用本地内存。
因此,默认情况下,元空间的大小仅受本地内存限制。
四、JVM垃圾回收与算法
确认垃圾方法1 : 引用计数法
引用和对象是有关联的。如果要操作对象则必须用引用进行。
通过引用计数来判断一个对象是否可以回收。
即一个对象如果没有任何与之关联的引用,即他们的引用计数都不为0,则说明对象不太可能再被用到,那么这个对象就是可回收对象。
确认垃圾方法2 : 可达性分析法
为了解决引用计数法的循环引用问题,Java使用了可达性分析的方法。
通过一系列的“GC roots”对象作为起点搜索。如果在“GC roots”和一个对象之间没有可达路径,则称该对象是不可达的。
要注意的是,不可达对象不等价于可回收对象,不可达对象变为可回收对象至少要经过两次标记过程。两次标记后仍然是可回收对象,则将面临回收。
垃圾回收算法
垃圾回收算法1 : 标记清除算法(Mark-Sweep)
过程 -> 最基础的垃圾回收算法,分为两个阶段,标注和清除。标记阶段标记出所有需要回收的对象,清除阶段回收被标记的对象所占用的空。
问题 -> 该算法最大的问题是内存碎片化严重,后续可能发生大对象不能找到可利用空间的问题。
垃圾回收算法2 : 复制算法(copying)
为了解决Mark-Sweep算法内存碎片化的缺陷而被提出的算法。
过程 -> 按内存容量将内存划分为相等大小的两块。每次只使用其中一块,当这一块内存满后将尚存活的对象复制到另一块上去,把已使用的内存清掉
问题 -> 问题是可用内存被压缩到了原本的一半。
垃圾回收算法3 : 标识整理算法(Mark-Compact)
过程 -> 标记阶段和Mark-Sweep 算法相同,标记后不是清理对象,而是将存活对象移向内存的一端。然后清除端边界外的对象。
垃圾回收算法4 : 分代收集法
分代收集法是目前大部分JVM 所采用的方法,其核心思想是根据对象存活的不同生命周期将内存划分为不同的域,一般情况下将GC 堆划分为老生代(Tenured/Old Generation)和新生代(YoungGeneration)。
老生代的特点是每次垃圾回收时只有少量对象需要被回收,新生代的特点是每次垃圾回收时都有大量垃圾需要被回收,因此可以根据不同区域选择不同的算法。
在新生代-复制算法
每次垃圾收集都能发现大批对象已死, 只有少量存活。因此选用复制算法, 只需要付出少量存活对象的复制成本就可以完成收集.
在老年代-标记整理算法
因为对象存活率高、没有额外空间对它进行分配担保, 就必须采用“标记—清理”或“标记—整理”算法来进行回收, 不必进行内存复制, 且直接腾出空闲内存.
垃圾回收算法5 : 分区收集算法
分区算法则将整个堆空间划分为连续的不同小区间, 每个小区间独立使用, 独立回收.
这样做的好处是可以控制一次回收多少个小区间 , 根据目标停顿时间, 每次合理地回收若干个小区间(而不是整个堆), 从而减少一次GC 所产生的停顿。
五、GC垃圾收集器
1. Serial垃圾收集器(单线程 复制算法)
Serial(英文连续)是最基本垃圾收集器,使用复制算法。是java 虚拟机运行在Client 模式下默认的新生代垃圾收集器。
2. ParNew垃圾收集器(Serial 多线程)
ParNew 垃圾收集器其实是Serial收集器的多线程版。
ParNew 收集器默认开启和CPU数目相同的线程数,可以通过-XX:ParallelGCThreads参数来限制垃圾收集器的线程数。
Java虚拟机运行在Server模式下新生代的默认垃圾收集器。
3. Parallel Scavenge 收集器(多线程复制算法)
自适应调节策略是Parallel Scavenge收集器与ParNew收集器的一个重要区别。
4. Serial Old收集群(单线程标记整理算法)
Serial Old 是Serial 垃圾收集器年老代版本,它同样是个单线程的收集器,使用标记-整理算法,
这个收集器也主要是运行在Client 默认的java 虚拟机默认的年老代垃圾收集器。
5. Parallel Old 收集器(多线程标记整理算法)
Parallel Old 收集器是Parallel Scavenge的年老代版本,使用多线程的标记-整理算法,在JDK1.6才开始提供。
6. CMS 收集器(多线程标记清除算法)
Concurrent mark sweep(CMS)收集器是一种年老代垃圾收集器,其最主要目标是获取最短垃圾回收停顿时间,
和其他年老代使用标记-整理算法不同,它使用多线程的标记-清除算法。
1) 初始标记 : 标记一下GC Roots 能直接关联的对象,需要暂停所有的工作线程。
2) 并发标记 : 进行GC Roots 跟踪的过程,和用户线程一起工作,不需要暂停工作线程。
3) 重新标记 : 标记产生变动的那一部分对象的标记记录,仍然需要暂停所有的工作线程。
4) 并发清除 : 清除GC Roots 不可达对象,和用户线程一起工作,不需要暂停工作线程。
7. G1 收集器
Garbage first 垃圾收集器是目前垃圾收集器理论发展的最前沿成果,相比与CMS 收集器,G1 收集器两个最突出的改进是:
1) 基于标记-整理算法,不产生内存碎片。
2) 可以非常精确控制停顿时间,在不牺牲吞吐量前提下,实现低停顿垃圾回收。
G1 收集器避免全区域垃圾收集,它把堆内存划分为大小固定的几个独立区域
相关推荐
2. **垃圾回收算法**: - **标记-清除(Mark-Sweep)**:首先标记出所有活动对象,然后清除未标记的对象。缺点是容易产生内存碎片。 - **复制(Copying)**:将内存分为两块,每次只使用一块,当一块用完后,将...
5. 垃圾收集器:自动回收不再使用的对象,释放内存。 三、JVM内存模型 1. 方法区:存储类信息、常量、静态变量等。 2. 堆:所有对象实例都在此分配内存,是垃圾收集的主要区域。 3. 虚拟机栈:每个线程都有一个独立...
所有通过`new`创建的对象都在堆中分配内存,由垃圾回收器负责回收。堆的大小可配置,通过`-Xms`和`-Xmx`设定。 ### 1.1.2 JVM内存结构及功能概述 - **方法区(Method Area)**:存储类的信息,如类名、字段、方法...
【JVM垃圾收集器概述】 Java虚拟机(JVM)的垃圾收集器是自动管理内存的重要组成部分,负责识别不再使用的对象并释放它们所占用的内存,以防止内存泄漏。垃圾收集器的选择和配置对应用程序的性能有着显著影响,特别...
#### 二、内存区域概述 Java虚拟机(JVM)将内存分为几个主要区域,每个区域都有其特定的功能和用途。这些区域包括程序计数器、Java虚拟机栈、本地方法栈、Java堆和方法区。下面我们将重点介绍其中与内存管理密切相关...
2. **内存管理**:JVM提供了自动内存管理机制,包括垃圾收集器,可以自动回收不再使用的对象所占用的内存空间。 3. **安全性**:JVM提供了沙箱安全模型,确保运行中的Java程序不会对操作系统造成损害。 #### 二、...
第40讲 垃圾收集器-parallel收集器详解 00:11:02 第41讲 垃圾收集器-cms收集器详解 00:14:58 第42讲 最牛的垃圾收集器-g1收集器详解 00:18:04 第43讲 内存分配-概述 00:04:23 第44讲 内存分配-Eden...
JVM概述 ##### 1.1 Java的特性与JVM的应用 Java语言的特性包括跨平台性、面向对象、安全性等。JVM是Java程序能够跨平台运行的关键,它负责将Java源代码转换成与平台无关的字节码,然后在不同平台的JVM上解释执行...
第40节垃圾收集器-parallel收集器详解00:11:02分钟 | 第41节垃圾收集器-cms收集器详解00:14:58分钟 | 第42节最牛的垃圾收集器-g1收集器详解00:18:04分钟 | 第43节内存分配-概述00:04:23分钟 | 第44节内存分配-...
1. **JVM概述**: - JVM是Java平台的核心组成部分,它是一个运行Java字节码的虚拟机,负责执行Java程序。 - JVM实现了Java的跨平台特性,即“一次编写,到处运行”。 2. **类加载机制**: - 类的生命周期包括...
理解了应用程序的工作负荷和jvm支持的垃圾收集算法,便可以进行优化配置垃圾收集器。 垃圾收集的目的在于清除不再使用的对象。gc通过确定对象是否被活动对象引用来确定是否收集该对象。gc首先要判断该对象是否是...
- **CMS收集器**:Concurrent Mark Sweep收集器,是一种以获取最短回收停顿时间为目标的收集器。它适合于对响应时间要求较高的场合。需要注意的是: - 对CPU资源敏感。 - 空间碎片问题。 - 无法处理浮动垃圾。 #...
- **内存区域划分**:JVM的内存被划分为不同的区域,如堆区、方法区、栈区等,每个区域都有其特定的功能和管理机制。 - **垃圾回收机制**:JVM通过自动垃圾回收机制来管理对象的生命周期,了解其工作原理有助于...
4. **垃圾收集器(Garbage Collector, GC)**:自动回收不再使用的内存,避免内存泄露。常见的GC算法有标记-清除、复制、标记-整理和分代收集。 5. **本地方法接口(Native Method Interface, JNI)**:允许Java...
Java堆是JVM中最为重要的内存区域之一,其主要用来存储对象实例。为了提高垃圾回收效率,通常会将堆划分为不同的区域,例如**新生代**和**老年代**。新生代进一步分为**Eden**区和两个**Survivor**区(S0、S1)。...
1. **JVM概述** - JVM是Java语言的运行环境,它负责执行字节码并管理内存,为开发者提供了跨平台的编程能力。 - JVM包含几个关键区域:堆(Heap)、方法区(Method Area)、栈(Stack)、程序计数器(PC Register...
JVM的垃圾收集器自动管理内存,回收不再使用的对象所占用的空间,防止内存泄漏。常见的垃圾收集算法有标记-清除、复制、标记-整理和分代收集。现代JVM如G1、ZGC和Shenandoah等提供了更高效的内存回收策略。 【JVM...
常用的GC回收算法包括但不限于:串行收集器、并行收集器、CMS收集器、G1收集器等。 #### 六、JVM的死法 - **Heap溢出**:当JVM堆无法再分配更多内存时,会导致Heap溢出错误。 - **ThreadStack溢出**:如果线程...
1. 垃圾收集:Java 11的JVM改进了垃圾收集算法,例如ZGC(Z Garbage Collector)提供了低延迟的内存回收。ZGC通过颜色标记、并发标记、重分配和屏障技术,实现了在大规模堆内存下的高效垃圾回收。 2. 分代内存模型:...
- **垃圾回收算法**:主要有标记-清除算法、复制算法、标记-整理算法、分代收集算法等。 - **标记-清除算法**:分为“标记”和“清除”两个阶段。缺点是效率低且会产生大量不连续的内存碎片。 - **复制算法**:将...