Java JVM 内存结构有哪些
生活里咱们常说“手机卡了”“电脑变卡了”,多半是设备里的“小仓库”(内存)不够用了。写Java程序时,也会碰到类似的卡顿、报错问题,这往往和JVM的内存结构有关——咱们就像给程序找了个专门的“管家”来管内存,这个管家就是JVM,它把内存分成了不同的“功能区”,每个区管不同的事,咱们可以用家里的储物空间来类比,轻松搞懂。
一、先记两个“固定不变的公共区域”
这两个区域是JVM启动后就有,直到JVM关门(停止运行)才消失的,相当于家里的“公共客厅”和“玄关”,是所有人共用的地方。

第一个是方法区,可以类比成家里的“客厅”。客厅里放的是大家都能用的固定物品:比如Java程序里的“类信息”(就像客厅里的沙发、茶几,是固定的家具)、“静态变量”(比如放在茶几上的常用水杯,全家都能拿)、“常量池”(比如墙上挂的装饰画,是固定不变的内容)。不管程序跑多久,这些东西都在客厅里,不会随便丢。
第二个是堆内存,这个类比成家里的“储物间”最合适。咱们平时买的东西、用的零碎,比如衣服、玩具,都堆在储物间里,用的时候拿,不用就放回去。堆内存就是用来放Java里的“对象实例”——比如程序里新建的一个用户对象、一个订单对象,都存在这里。而且这个区域是JVM里最大的一块,也是垃圾回收(就是清理不用的旧东西)最主要的地方,相当于每周清理一次储物间,把旧衣服、不用的玩具扔掉,给新东西腾地方。
二、再分三个“跟着线程走的临时区域”
剩下的三个区域,是每个“来家里做客的人”(也就是程序里的“线程”)专属的临时空间,相当于每个人进门后自己用的“随身小包”“笔记本”“餐桌”,客人走了这些东西就没了,不会占用公共空间。
第一个是程序计数器,可以类比成咱们手机里的“书签”。当咱们刷视频时,停在第10分钟的位置,下次打开就能接着看,不用重新从头找。程序计数器就是干这个的:每个线程在跑的时候,都会记录当前执行到哪一行代码,比如今天写代码的第10行,明天接着打开就能从第11行继续,保证线程不会乱掉。
第二个是虚拟机栈,类比成咱们写作业用的“草稿本”。每次写作业要算题,会在草稿本上写步骤,算完这道题,这部分草稿就没用了。虚拟机栈就是用来管“方法调用”的:比如程序里要算“1+2”,会先把这个计算的步骤写在栈里,算完结果后,这个步骤就从草稿本上撕掉。每调用一个新方法,就会在栈里加一页草稿;方法结束,这页就消失,所以栈里的内容是临时的,跟着线程走。
第三个是本地方法栈,这个类比成家里的“厨房操作间”。咱们做饭时,用的是家里的厨具(本地系统的功能),不是客厅的家具。本地方法栈就是专门给Java调用系统自带的功能用的,比如调用系统的录音、拍照功能,这部分操作的内存就存在这里,也是线程专属,用完就没。
三、记住两个容易混淆的小细节
很多初学者容易把方法区和堆搞混,其实很好区分:方法区放的是“固定的公共信息”,比如类的模板,不管new多少个对象,都共用一套模板;堆放的是“每个对象的具体内容”,比如new了10个用户对象,堆里就有10份各自的信息,而方法区里只有一份用户类的模板。
另外,这几个区域的大小是可以调整的,就像家里的储物间,不够用就多隔点空间,太大就缩小,JVM可以通过参数设置每个区的大小,这样就能适配不同的程序需求。
搞懂JVM的内存结构,就像摸清了家里的各个储物区,以后碰到程序报错“内存溢出”“栈溢出”,就能快速找到问题出在哪——是储物间(堆)放满了旧对象没清理,还是草稿本(栈)写的步骤太多没及时删,再也不会懵懵懂懂啦。