Jvm系列之内存结构

本文详细解析Java虚拟机(JVM)的内存布局,包括线程私有的栈、方法区和堆,阐述各部分的功能、异常及参数配置,适合希望深入了解JVM内部机制的开发者。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

       最近几个月比较忙,现在项目组忙完了,有一段休息时间,就没事看看java虚拟机相关的内容,经过几天的梳理,将相关的知识记录下来,若中间讲的出现了错误或不足之处,望各位大兄弟给指出来。

       JVM大致分为三个区域,栈、方法区、堆,其中栈是线程私有的,不共享,方法区和堆是线程共有的,线程共享,至于为什么,下面将有详细的介绍。

一、栈

栈中主要包括程序计数器、java虚拟机栈、本地方法栈三个模块

1.程序计数器

       程序计数器是每个线程都有的,其记录当前线程正在执行的字节码指令的位置。因为java虚拟机的多线程是将线程进行切换,分配给线程不同的cpu执行时间来实现的,因此每个线程都要记录其各自执行指令的位置。所以程序计数器是线程私有的

2.java虚拟机栈

       java虚拟机栈是java方法执行时的内存结构,当java方法执行时,虚拟机会为其创建一个“栈帧”,用来存储局部变量表、动态链接、操作数栈、方法的出口,当方法执行结束,该栈帧从java虚拟机栈中出栈。

       局部变量表包括基本数据类型和对象的引用。

        该区域会出现两种异常,当线程请求的栈深度大于java虚拟机所允许的的深度时,会抛出StackOverFlowError(栈溢出)的异常;若java虚拟机栈可扩展的(一般现在的java虚拟机栈都可动态扩展,但是也存在不可扩展的java虚拟机栈),若扩展时无法申请到足够的内存,则会抛出OutOfMemoryError(内存不足)的异常。

3.本地方法栈

       本地方法栈是执行本地方法所创建的本地方法栈。本地方法栈服务的对象是JVM执行的native方法,而虚拟机栈服务的是JVM执行的java方法。例如创建对象时的new就是native方法。我们常用的hotSpot虚拟机已经将本地方法栈和java虚拟机栈合并了。

二、方法区

       方法区又称为永久代(PermGen),为了跟堆区分开,又称为“非堆”,但其实只是称呼方法区为永久代,其实其跟永久代还有本质区别,而且永久代还是针对hotSpot虚拟机来讲的,在其他虚拟机上不存在永久代,而且hotSpot在java8时舍弃了永久代,取而代之的是元空间,元空间不在虚拟机上,使用的是本地内存

       方法区中存放的是常量、静态变量以及类的信息,从存放的数据就可以看出为什么是线程共享的了,其中类的信息就是类的构造函数、方法、属性。java虚拟机对该区域的规范特别宽松,其内存可以是连续的也可以是不连续的,其大小可以扩展也可以是固定的。

       这个区域的内存回收现象是特别少的,但是并不代表进入该区域就跟真的进入永久代一样永远存在,该区域主要发生回收的是常量池,主要是常量的回收以及类型的卸载,但一般该区域的内存回收不是那么理想,而类型的卸载条件更是苛刻。但是该区域的回收还是很必要的,并不能因为难以回收而不回收。

三、堆

       堆中存放的是程序运行过程中创建的对象的实例,jvm中垃圾的回收主要集中在该区域,程序运行创建的实例会越来越多,由于硬件条件的限制,需定时清理不再使用的实例,否则会导致内存不足。因此堆和方法区的常量池是jvm进行垃圾回收的主要区域。

       堆又分为年轻代(Young Generation)和老年代(Old Generation),年轻代又分为Eden区、Survivor From区、Survivor To区,其中eden:From:To的默认比例是8:1:1,两个Survivor的大小一致,一般来讲老年代要比年轻代大,最底线的情况时两者大小一致,即1:1。

结构图如下:

       垃圾回收主要分为Minor GC以及Full GC,Minor GC是年轻代的垃圾回收,Full GC是整个堆的垃圾回收,即对年轻代进行回收,又对老年代进行回收,Minor GC回收的时间短,Full GC回收耗费的时间长。还有一个Major GC,这个不常用

       程序中新创建的对象,都在Eden和From区,To区是空的,年轻代的数据几乎都是朝生夕死,该区域回收的概率达到了80%,当进行一次Major GC后,Eden和From区域存活下来的对象都会被复制到To区域,Eden和From清空,此时From和To区域互相调换,From变成To,To变成From,并且将这些对象的年龄设置为1,以后对象在Survivor区每经过一次Minor GC,就将对象的年龄加1,当对象的年龄达到某个值(阈值)时(默认是15岁,使用参数-XX:MaxTenuringThreshold可以调整)这些对象就会成为老年代。

各个区域设置大小的相应参数:

-Xms:堆的最小空间

-Xmx:堆的最大空间

-Xmn:年轻代的空间

-Xss:每个线程的大小

-XX:NewSize:年轻代最小空间

-XX:MaxNewSize:年轻代的最大空间

-XX:PermSize:持久代的最小空间

-XX:MaxPermSize:持久代的最大空间

没有设置老年代的大小的参数,但是可以通过堆大小和年轻代大小来计算(老年代空间大小=堆空间大小-年轻代空间大小)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值