Java虚拟机内存模型
如果你想理解Java垃圾回收如果工作,那么理解JVM的内存模型就显的非常重要。今天我们就来看看JVM内存的各不同部分及如果监控和实现垃圾回收调优。
1、Stop the World Event
所有的垃圾回收都是“阻塞”事件(“Stop the World” events) ,因为所有应用程序线程必须停止,直到垃圾回收操作完成之后才能继续。
由于年轻代总是保存着短期存活的对象,最小化GC非常快,应用程序也不会受到影响。然而大GC(Major GC)由于它要检查所有存活的对象,所以需要花费很长的时间。 大GC会在垃圾回收期间使得你的应用程序没有任何响应,应最大化的减少此类GC。如果你有一个即时响应应用程序且总是有很多的大GC在执行。你会发现存在超时错误。
垃圾回器扫行的时间依赖于GC所使用的策略。这就是为什么对于那些高响应用程序来说,GC的监控与调优显得非常必要。
2、JVM内存模型
正如你上图所看到的,JVM内存可以划分为不同的部分,广义上,JVM堆内存可以划分为两部分:年轻代和老年代(Young Generation and Old Generation)
3、年轻代(Young Generation)
年轻代用于存放由new所生成的对象。当年轻代空间满时,垃圾回收就会执行。这个垃圾回收我们称之为 最小化垃圾回收(Minor GC)。年轻代又可以分为三分部: 一个Eden内存区(Eden Memory)和两个Survivor 内存区(Survivor Memory)。
关于年轻代的重点:
- 大多数新创建的对象都存放在Eden内存区。
- 当Eden区存满对象时,最小化GC将会被执行,所有存活的对象被移到其中一个Survivor区。
- 最小化GC同时也会检查存活的对象并将它们移到另一个Survivor区,所以在一段时间,其中一个Survivor区总是空的。
- 存活的对象经过多次GC后,将会被移到老年代(Old Generation)通常年轻代转化多长时间变为老年代都会设置一个阀值。
4、老年代(Old Generation)
老年代内存包含那些经过多次最小化GC且存活的对象。 通常当老年代内存满时垃圾回收会被执行。我们称之为大GC (Major GC),通常这个过程会花费很长的时间。
5、永久代(Permanent Generation)
永久代或持久代包含JVM用来描述应用程序中使用的类和方法的元数据。注意 永久代不是JAVA堆内存的一部分。
JVM在运行期间依据应用程序所使用的类来存入永久代,同时也包含Java SE库类各方法。 永久代中的对象通过全GC(Full GC)来进行垃圾回收。
方法区Method Area
方法区是永久代的一部分,用于存储类结构(运行时的常量和静态变量)及方法和构造的代码。
运行时常量池Runtime Constant Pool
运行时常量池是类中常量池在编译期的表示,它包含类的运行时常量,静态方法,它是方法区的一部分。
Java栈内存Java Stack Memory
Java 栈内存用于执行线程。包含方法短期存活的特定值及方法中所涉及的指向堆中其它对象的引用。
Java 堆内存Switches(Java Heap Memory Switches)
提供了大量的内存Switch,我们可以用来设置内存大小及它们的比率。一此常用的内存Switches如下。
VM Switch | VM Switch 描述 |
---|---|
-Xms | 设置JVM启动时堆初始值。 |
-Xmx | 设置堆的最大值 |
-Xmn | 设置年轻代的大小 |
-XX:PermGen | 设置永久代内存的初始值 |
-XX:MaxPermGen | 设置永久代内存的最大值 |
-XX:SurvivorRatio | 用于提供Eden区和Survivor区的比例, 例如,如果年轻代的大小为 10M,VM switch is -XX:SurvivorRatio=2 那么 5 M 分配给 Eden 区,每一个Survivor 区为 2.5 M .默认比例大小为 8。 |
-XX:NewRatio | 老年代/新生代的比例. 默认值是 2. |
大多数情况下,上述选项是非常有用的。如果你也想试试其它参数可以查看 JVM 官方主页
6、JAVA GC
Java GC是从内存中标记、移除非可用对象并释放所分配的空间用于后续创建对像的过程。Java编程语言最大的功能之一就是自动垃圾回收。不像其它类似C的编程语言,它们的内存分配与回收可以人为操作。
GC是后台执行用于检查内存中的所有对象并找出未被任务程序所引用的对象。所有这些未引用的对象将被删除,同时空间也会被回收用于分配给其它对象。
关于标记、删除方法有两个问题:
1.由于新创建的对象将会变成不可用,所有效率上不是很高。
2.多次GC后可用的对象很能在后续的GC后仍然可用。
上述方法的不足在于Java的GC是分代的,在堆内存中分年轻代和老年代。 前面我已经解释过基于最小化GC(Minor GC)和大GC(Major GC)对象是如果被扫描并从一个分代区移到别一个分区。
Java GC的类型
在应用程序中我们可以使用如下五种类型的GC。我们可以使用JVM相关设置为应用程序开启GC策略,现在我们就来具体的看看.
- 串行GC (Serial GC -XX:+UseSerialGC): 串行GC为年轻代和老年代GC提供简单的标记-清除-压缩方法。串行GC在独立应用程序运行的少量CPU的客户机器上非常有效。对于那些低内存占用的应用程序非常有利。
- 并行GC (Parallel GC -XX:+UseParallelGC): 并行GC中大部分实现与串行GC相同,除了年轻代的垃圾回收使用N个线程,N是系统CPU内核的数量。我们可以通过 JVM 的 -XX:ParallelGCThreads=n 选项来控制线程的数量。并行的垃圾回收器因为使用多CPU来加速GC的实现所以也称为并行收集器(throughput collector).并行GC使用单线程来处理老年代的垃圾回收.
- 并行Old GC (Parallel Old GC -XX:+UseParallelOldGC):此类型的GC中年轻代和老年代GC都使用多线程进行。其它与并行GC相同,
- 并发标记清除收集器(Concurrent Mark Sweep (CMS) Collector) (-XX:+UseConcMarkSweepGC): CMS收集器是并发短暂停收集器。它为老年代进行垃圾回收。CMS收集器 通过与应用程序线程并发执行垃圾回收 从而缩短因GC而出现的暂停时间。CMS收集器在年轻代使用与并行收集器相同的算法。这类垃圾收集器适合不能容忍长时间暂停的响应程序。我们可以通过JVM中的 -XX:ParallelCMSThreads=n 来设置CMS收集器中的线程数。
- G1 垃圾收集器G1 Garbage Collector (-XX:+UseG1GC) Java 7中可以使用G1 垃圾收集器。它的最终目标是替换掉CMS收集器。G1收集器是一个并行、并发、增量压缩、低暂停的垃圾收集器。
G1垃圾收集器不同于其它收集器,它没有年轻代、老年代空间,它将堆空间划分成多个相同大小的堆区域(heap regions),当调用一次垃圾回收,它首先收集实时性不是很高的区域的数据,因此称为”Garbage First”。
以上是 Java虚拟机内存模型 的全部内容, 来源链接: utcz.com/z/391718.html