JVM内存模型以及HotSpot的GC策略

概述

想要进一步掌握Java语言,必须要深入了解一下Java程序的运行环境。本文会对JVM的内存模型、Java内存自动管理机制、以及Oracle官方虚拟机HotSpot在GC方面的实现策略进行大概的梳理。

什么是Java的内存模型?

众所周知,Java程序是运行在JVM上面的,但是不具体指定是哪一款JVM,只要是符合一定的规范的JVM,都可以正确的运行Java字节码。该规范由Oracle官方提供,旨在描述一个抽象的JVM,它包含很多部分,包括class文件结构、运行时内存状态、指令集等。

而上述所说的运行时内存状态这一部分,就是常说的JVM(Java) 的内存模型。它主要描述的是运行时,各类型数据在内存中的呈现方式。JVM内存模型并没有指定该呈现方式的具体实现方式,而是指定了一些逻辑上应该拥有的模块,以及每个模块的作用域、大小、存放的数据类型等信息。

Java语言规定的内存模型是什么样子?

JVM规范给出了运行时的内存模型,应该包含的一些模块,以及每个模块的特性,如下图所示:

什么是GC?

通常所说的GC,可以叫做Garbage Collection 或者 Garbage Collector,GC既是表明一种内存管理机制,也可以看做是内存管理程序,这里不做详细区分。Java跟C++的很大的一个区别就是,内存自动管理机制。既然是内存自动管理,那么就涉及到内存的分配与回收问题。而且是自动的,所以在Java程序运行时,JVM中肯定还有一个负责做这件事的程序,这就是GC。

GC有自己的责任,主要有下面几个职责:

分配内存 - 为新的对象分配请求寻找足够的内存空间。

回收垃圾内存 - 当内存满了,不能为新对象分配内存时、或者内存使用达到一定的百分比时,回收掉那些不再被使用的对象(垃圾对象)。

整理内存碎片 - 回收完成后,可能会有很多不连续的内存空间,叫做内存碎片。整理碎片,有助于下次更快的为新对象分配内存。

什么是内存垃圾?

Java是面向对象语言,正常都是操作对象,那么当一个对象用完后,不再需要使用的时候,它就变成了内存垃圾。在JVM中,主要是通过GC Roots来实现垃圾对象的识别。当一个对象,从任何的GC Roots开始,都不能访问到该对象时,该对象就是垃圾对象。

GC Roots的定义如下:

Class - 系统ClassLoader加载的class,这些类不能被卸载。他们可以通过static变量来持有对象。自定义的ClassLoader不是GC Roots。

Thread - 还存活的Thread。

JVM Stack - 本地变量或者方法的参数。

JNI Local - Native方法的本地变量或者参数。

JNI Global - 全局的JNI引用。

Held By JVM - 系统的ClassLoader、一小部分JVM知道的重要的Exception、一些为处理异常而预先分配的对象、正在loading class的自定义ClassLoader。

如何衡量一个GC的性能?

生产能力 - 应用程序运行的时间与总运行时间的比例。

GC运行的额外消耗 - GC程序运行的时间与总运行时间的比例。

暂停时间 - GC运行时,应用程序暂停的时间。

GC频率 - GC的执行频率

覆盖的区域大小 - GC工作的区域大小。

垃圾回收的及时性 - 一个对象成为垃圾对象到被回收的时间。

HotSpot是怎么实现GC策略的?

HotSpot采用了分代管理的方式。不同的内存区域的对象,存活的年龄不一样。

1、新生代(young generational)

大多数对象直接分配在新生代的Eden区域(一些大对象直接分配在老年代),Survivors 的 From 区域保存那些在至少一次新生代GC之后活下来,但是还不能被认为是“足够老”的对象,它们有更多死亡的机会。而这时 To 区域是空的。这两个区域交替变换身份(下一次GC,现在的 To 区域就变为 From 区域)。

2、老年代(old generational)

包含从新生代存活下来的对象,以及一些直接分配在老年代的大对象,

3、持久代(permanent generational)

包含那些JVM的 gc collector 方便管理的对象,比如类或者方法的描述对象,以及类和对象本身。Method Area 和 Run-Time Constant Pool。

有哪些GC类型?

1、minor collection(young generational collection)

触发条件:当新生代区域满的时候,会触发。

回收区域:只对新生代进行回收。

2、full collection(major collection)

触发条件:老年代或者持久代区域满的时候,会触发。

回收区域:三个区域都会被回收。

HotSpot中有哪些Garbage Collector?

1、Serial Collector

在Serial Collector中,不管是 新生代 还是 老年代/永久代,都是串行执行,使用一个CPU。当执行GC时,应用程序就会被暂停,不被执行。

young generational 的回收方式:

Eden区域存活的对象,被复制到Survivor中为空的To区域。如果有To区域容纳不下的大对象,则直接复制到old generational。

From区域中存活的相对年轻的对象,被复制到To区域中。存活的相对老的对象,被复制到old generational。

当To区域不够容纳存活对象时,这些存活对象直接被复制到old generational,不管它们经历了多少次young generational collection。

清空Eden和From,现在From变为了To,而To变为了From。

回收前:

回收后:

old generational(permanent generational) 的回收方式

Serial Collector 对 old generational区域实行Mark-Sweep-Compact的算法。该算法分为三个步骤,如下所示:

Mark - 标记出还存活的对象。

Sweep - 清理掉垃圾对象。

Compact - 执行移动压缩,把所有存活对象平移到开始趋区域。让尾部留出连续的空间,这样后面为对象可以快速分配空间。

回收前后:

2、parallel collector

young generational 的回收方式:

跟Serial collector的算法一样,只是利用了多核的优势,并行执行。蓝色为并行的应用程序,黄色为GC程序。

old generational (permanent generational)的回收方式:

跟Serial collector的算法一样,只是利用了多核的优势,并行执行。

时间: 2024-12-26 21:20:58

JVM内存模型以及HotSpot的GC策略的相关文章

jvm的stack和heap,JVM内存模型,垃圾回收策略,分代收集,增量收集(转)

深入Java虚拟机:JVM中的Stack和Heap(转自:http://www.cnblogs.com/laoyangHJ/archive/2011/08/17/gc-Stack.html) 在JVM中,内存分为两个部分,Stack(栈)和Heap(堆),这里,我们从JVM的内存管理原理的角度来认识Stack和Heap,并通过这些原理认清Java中静态方法和静态属性的问题. 一般,JVM的内存分为两部分:Stack和Heap. Stack(栈)是JVM的内存指令区.Stack管理很简单,push

JVM内存模型及垃圾收集策略解析

AD: JVM内存模型是Java的核心技术之一,之前51CTO曾为大家介绍过JVM分代垃圾回收策略的基础概念,现在很多编程语言都引入了类似Java JVM的内存模型和垃圾收集器的机制,下面我们将主要针对Java中的JVM内存模型及垃圾收集的具体策略进行综合的分析. 一 JVM内存模型 1.1 Java栈 Java栈是与每一个线程关联的,JVM在创建每一个线程的时候,会分配一定的栈空间给线程.它主要用来存储线程执行过程中的局部变量,方法的返回值,以及方法调用上下文.栈空间随着线程的终止而释放.St

JVM内存模型与GC算法(简介)

JVM内存模型如上图,需要声明一点,这是<Java虚拟机规范(Java SE 7版)>规定的内容,实际区域由各JVM自己实现,所以可能略有不同.以下对各区域进行简短说明. 1.1程序计数器 程序计数器是众多编程语言都共有的一部分,作用是标示下一条需要执行的指令的位置,分支.循环.跳转.异常处理.线程恢复等基础功能都是依赖程序计数器完成的. 对于Java的多线程程序而言,不同的线程都是通过轮流获得cpu的时间片运行的,这符合计算机组成原理的基本概念,因此不同的线程之间需要不停的获得运行,挂起等待

【转】jvm 内存模型及内存调优

一,JVM内存模型概括 还有一个寄存器,线程运行于其上面 1.程序计数器 记录线程的执行位置,线程私有内存,唯一一个在Java虚拟机规范中没有规定任何OutOfMemoryError情况的区域 2.线程栈(VM stack) 栈的默认大小是1M -Xss2m 这样设置成2M 异常 :Fatal: Stack size too small 异常的引起一般是线程数目太多 3.本地方法栈(native stack) 即为一些Native方法分配的stack 异常:java.lang.OutOfMemo

JVM内存模型 三

本文章节: 1.JMM简介 2.堆和栈 3.本机内存 4.防止内存泄漏 1.JMM简介 i.内存模型概述 Java平台自动集成了线程以及多处理器技术,这种集成程度比Java以前诞生的计算机语言要厉害很多,该语言针对多种异构平台的平台独立性而使用的多线程技术支持也是具有开拓性的一面,有时候在开发Java同步和线程安全要求很严格的程序时,往往容易混淆的一个概念就是内存模型.究竟什么是内存模型?内存模型描述了程序中各个变量(实例域.静态域和数组元素)之间的关系,以及在实际计算机系统中将变量存储到内存和

JVM内存模型理解

Java虚拟机(Java VirtualMachine 简称JVM)是运行所有Java程序的抽象计算机,是Java语言的运行环境,它是Java 最具吸引力的特性之一. JVM内存模型 1.方法区和堆是所有线程共享的数据区 1)堆:存放对象的实例 2)方法区:存放已被虚拟机加载的类信息.常量.静态变量.即时编译器编译后的代码 3)运行时常量池:是方法区的一部分,存放Class的版本.字段.方法.接口等描述信息,字符串池就是这个!!! 2.程序计数器.虚拟机栈.本地方法栈是线程隔离的数据区 4)程序

JVM内存模型及垃圾回收机制

JVM内存模型1.栈Java栈是与每一个线程关联的,JVM在创建每一个线程的时候,会分配一定的栈空间给线程.存储局部变量.引用.方法.返回值等.StackOverflowError:如果在线程执行的过程中,栈空间不够用,那么JVM就会抛出此异常,这种情况一般是死递归造成的.2.堆 Java中堆是由所有的线程共享的一块内存区域,堆用来保存各种JAVA对象,比如数组,线程对象等. 2.1堆的分代JVM堆一般分为三个部分:Young:年轻代Young区被划分为三部分,Eden区和两个大小严格相同的Su

JVM内存模型,垃圾回收算法

JVM内存模型总体架构图 程序计数器多线程时,当线程数超过CPU数量或CPU内核数量,线程之间就要根据时间片轮询抢夺CPU时间资源.因此每个线程有要有一个独立的程序计数器,记录下一条要运行的指令.线程私有的内存区域.如果执行的是JAVA方法,计数器记录正在执行的java字节码地址,如果执行的是native方法,则计数器为空.虚拟机栈线程私有的,与线程在同一时间创建.管理JAVA方法执行的内存模型.每个方法执行时都会创建一个桢栈来存储方法的的变量表.操作数栈.动态链接方法.返回值.返回地址等信息.

java虚拟机:JVM内存模型

一.JVM内存模型图解 JVM 运行时数据区 (JVM Runtime Area) 其实就是指 JVM 在运行期间,其对JVM内存空间的划分和分配.网上找到两幅图如下所示(个人认为第二个图Native Method Stack应该画在Java Thead模块中):      二.各数据区域介绍 1.栈区 栈分为java虚拟机栈和本地方法栈 重点是Java虚拟机栈,它是线程私有的,生命周期与线程相同. 每个方法执行都会创建一个栈帧,用于存放局部变量表,操作栈,动态链接,方法出口等.每个方法从被调用