JVM内存模型分析

本文详细介绍了JVM的内存模型,包括程序计数器用于线程执行定位,虚拟机栈和本地方法栈分别管理Java方法和本地方法的调用,堆区存储对象实例,方法区存储类信息。文章还讨论了垃圾回收在这些区域的作用,特别是堆区的MinorGC和MajorGC。
摘要由CSDN通过智能技术生成


前言

本文是对JVM的内存模型进行分析,帮助同学们进行理解。


JVM(Java虚拟机)主要包括五块区域,分别是程序计数器、虚拟机栈、本地方法栈、堆、方法区。在JVM当中堆和方法区各有一个,一条线程有一个栈和一个程序计数器。五块区域中当中变化最频繁是栈,最先有数据的是方法区,垃圾回收器主要针对的是堆。

一、程序计数器

由于在JVM中多线程是通过线程轮流切换来换取CPU执行时间的,在任何一个确定的时刻,一个CPU只会执行一条线程的指令。因此,为了线程切换后能恢复到正确的执行位置,每条线程都需要一个独立的程序计数器。
在这里插入图片描述
JVM中的程序计数寄存器 (Program Counter Register)中,Register 的命名源于
CPU的寄存器,寄存器存储指令相关的现场信息。 CPU只有把数据装载到寄存器才能够运行。
这里,并非是广义上所指的物理寄存器,或许将其翻译为PC计数器(或指令计数器)会更加贴切(也称为程序钩子),并且也不容易引起一些不必要的误会。JVM中的PC寄存器是对物理PC寄存器的一种抽象模拟。

二、虚拟机栈

1)虚拟机栈是当前执行线程独占空间,以栈的数据结构形式存在。
2)虚拟机栈是线程执行的区域,它保存着一个线程中方法的调用状态。
3)每一个被线程执行的方法,为该栈中的栈帧,即每个方法对应一个栈帧。

在这里插入图片描述Java虚拟机栈是线程私有的,生命周期和线程一致,中存储的是一个个栈帧,每个栈帧对应着一个被调用的方法。方法调用的时候,该方法所需的内存空间在栈内存中分配,称为压栈。方法执行结束之后,该方法所属的内存空间释放,称为弹栈(栈内存遵循先进后出,后进先出的原则)。虚拟机栈中主要存储的是局部变量、引用、操作数栈、动态链接、方法的出口等信息。

三、本地方法栈

  • Java虚拟机栈用于管理Java方法的调用,而本地方法栈用于管理本地方法的调用。本地方法栈,也是线程私有的。
  • 本地方法是使用C语言实现的,它的具体做法是Native Method Stack中登记native方法,在Execution Engine执行时加载本地方法库。
  • 当某个线程调用一个本地方法时,它就进入了一个全新的并且不受虚拟机限制的世界,它和虚拟机拥有同样的权限。本地方法可以通过本地方法接口来访问虚拟机内部的运行时数据区,它甚至可以直接使用本地处理器中的寄存器,直接从本地内存的堆中分配任意数量的内存。
  • 本地方法栈与Java虚拟机栈的的作用和原理非常相似,其区别只不过是虚拟机栈为虚拟机执行Java方法(也就是字节码)服务,而本地方法栈则是为虚拟机使用到的Native方法服务。

四、堆区

堆可以是物理上不连续的内存空间,但是在存储逻辑上是连续的。如果问你是否所有对象都分配到堆上,你需要回答出来一个逃逸分析和栈上分配的观点,后面有提到。

一个JVM实例只存在一个堆空间,并且所有的线程共享堆内存。
堆内存分区:

Young Generation Space 新生区 Young/New

Tenure generation space 老年代 Old/Tenure

Permanent space 永久区/元空间 Perm

Java 7之前的堆内存示意图:
在这里插入图片描述新生区是类的诞生、成长、消亡的区域,一个类在这里产生、应用,最后被垃圾回收器收集,结束生命。

新生区又分为两部分:伊甸园区(Eden space)和幸存者区(Survivor space)。所有的类都是在伊甸园区被new出来的。

幸存区有两个:0区(Survivor 0 space)和1区(Survivor 1 space).

当伊甸园区的空间用完时候,程序又需要创建对象,JVM的垃圾回收器将对伊甸园区进行垃圾回收(Minor GC,也叫轻GC 或者是YGC),将伊甸园区中的不再被其他对象所引用的对象进行销毁。然后伊甸园中的剩余对象移动到幸存0区(也叫from区)。若幸存0区也满了,在对该地区进行垃圾回收,然后移动到1区(也叫to区)。

如果1区也满了怎么办呢?在经历了15次YGC后,幸存1区也满了,那么这个时候,JVM将会把这些数据移动到养老区。如果养老区也满了,这个时候就会进行MajorGC(也称Full GC 检查FGC)。执行full GC对养老区的内存进行清理。如果养老区执行了Full GC之后,发现依然无法进行对象的保存,这个时候就会出现OOM(OutOfMemoryError)异常了。

如果出现了java.lang.OutOfMemoryError:java heap space异常。说明Java虚拟机的堆内存不够用了。主要原因有以下两种:

1:java虚拟机的堆内存设置不够,可以通过参数-Xms、-Xmx来调整

2:代码中创建了大量的大对象,并且长时间不能被垃圾回收器回收的(内存地址被引用了)

五、方法区

在这里插入图片描述

所有java 虚拟机线程共享的一块区域,存储了所有类相关信息,在虚拟机启动时被创建,JVM关闭就会释放方法区的空间。不同版本实现方式不同。例如永久代,元空间。

JDK1.6及之前:永久代。静态变量在永久代中

JDK1.7 :永久代。字符串常量池、静态变量移除,放入堆中。

JDK1.8及之后的实现方式:元空间。不在虚拟机设置的内存中,而是使用本地内存。类信息、字段、方法、常量保存在本地内存,但字符串常量池、静态变量仍在堆中。

The method area can also be garbage collected. Because Java programs can be dynamically extended via class loader objects, classes can become “unreferenced” by the application. If a class becomes unreferenced, a Java Virtual Machine can unload the class (garbage collect it) to keep the memory occupied by the method area at a minimum. The unloading of classes–including the conditions under which a class can become “unreferenced”–is described in Chapter 7, "The Lifetime of a Class."方法区也可以被垃圾回收,因为虚拟机允许通过用户定义的类装载器来动态扩展java程序,因此一些类也会成为程序“不再引用”的类。当某个类变为不再被引用的类时,Java虚拟机可以卸载这个类,从而使方法区占据的内存保持最小。类的卸载以及一个类变为“不再被引用”的必要条件。

方法区(Method Area)与Java堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。虽然Java虚拟机规范把方法区描述为堆的一个逻辑部分,但是它却有一个别名叫做Non-Heap(非堆),目的应该是与Java堆区分开来。

对于习惯在HotSpot虚拟机上开发和部署程序的开发者来说,很多人愿意把方法区称为“永久代”(Permanent Generation),本质上两者并不等价,仅仅是因为HotSpot虚拟机的设计团队选择把GC分代收集扩展至方法区,或者说使用永久代来实现方法区而已。对于其他虚拟机(如BEA JRockit、IBM J9等)来说是不存在永久代的概念的。即使是HotSpot虚拟机本身,根据官方发布的路线图信息,现在也有放弃永久代并“搬家”至Native Memory来实现方法区的规划了。

Java虚拟机规范对这个区域的限制非常宽松,除了和Java堆一样不需要连续的内存和可以选择固定大小或者可扩展外,还可以选择不实现垃圾收集。相对而言,垃圾收集行为在这个区域是比较少出现的,但并非数据进入了方法区就如永久代的名字一样“永久”存在了。这个区域的内存回收目标主要是针对常量池的回收和对类型的卸载,一般来说这个区域的回收“成绩”比较难以令人满意,尤其是类型的卸载,条件相当苛刻,但是这部分区域的回收确实是有必要的。在Sun公司的BUG列表中,曾出现过的若干个严重的BUG就是由于低版本的HotSpot虚拟机对此区域未完全回收而导致内存泄漏。

根据Java虚拟机规范的规定,当方法区无法满足内存分配需求时,将抛出OutOfMemoryError异常。

以上描述截取自:

《深入理解Java虚拟机:JVM高级特性与最佳实践》 作者: 周志明



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JH3073

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值