深入理解 JVM 之 JVM 内存结构

深入理解 JVM 之 JVM 内存结构

Java 虚拟机在运行 Java 程序 时,把它所管理的内存划分为若干个不同的数据区域,主要包括以下五个部分:程序计数器、Java 堆、Java 虚拟机栈、方法区和本地方法栈。

[图片上传失败...(image-656367-1607673231265)]

JVM 内存结构

程序计数器

程序计数器是当前线程所执行的字节码的行号指示器,它会指出下一条将要执行的指令的地址,字节码解释器就是通过改变计数器的值来选取程序接下来执行的操作。

程序计数器是线程私有的一小块内存,每条线程都要有一个独立的程序计数器,以使线程切换后恢复到正确的执行位置。

  • 如果线程正在执行 Java 方法,则计数器记录的是正在执行的虚拟机字节码指令的地址
  • 如果执行 native 方法,则计数器为空

它也是唯一一个不会出现 OutOfMemoryError 的内存区域。

Java 虚拟机栈

与程序计数器一样,Java 虚拟机栈也是线程私有的,在线程创建时 Java 栈会被创建,每个方法在在执行的同时都会创建一个栈帧,用于存放局部变量表,操作数栈,动态链接,方法出口等信息。每一个方法从调用直至执行完成,都对应着一个栈帧在虚拟机栈中入栈到出栈的过程。

一般所谓的“栈”,指的是虚拟机栈中局部变量表部分,其中存放了各种基本数据类型( 8 种),对象引用(reference 类型) 和 returnAddress 类型。局部变量表所需的空间在编译期就已经确定并完成分配,在方法运行期间不会被改变。

Java 虚拟栈中可能出现两种异常:

  • StackOverflowError:线程请求的栈深度大于虚拟机所允许的深度
  • OutOfMemoryError:虚拟机栈扩展时无法申请到足够的内存

本地方法栈

本地方法栈与 Java 虚拟机栈的作用类似,区别是 Java 虚拟机栈为虚拟机执行 Java 方法服务,而本地方法栈为虚拟机执行 Native 方法服务。有的虚拟机(例如 HotSpot 虚拟机)直接把本地方法栈和 Java 虚拟机栈合并在一起。

本地方法栈也可能会抛出 StackOverflowErrorOutOfMemoryError 异常。

Java 堆

Java 堆是是虚拟机中最主要的内存区域。它为线程共享,在虚拟机启动时创建,几乎所有的对象实例都存储在 Java 堆中。

Java 堆也被称作 "GC" 堆。从内存回收角度看,可分为新生代和老年代。而新生代又可分为 Eden 区、From Survivor 区、To Survivor 区等。

Java 堆的实现,既可以实现为固定的,也可以是扩展的。当前虚拟机都按照可扩展来实现,通过 -Xmx-Xms 控制堆大小。

如果堆中没有内存并且也无法再扩展时,会抛出 OutOfMemeoryError 异常。

方法区

方法区与 Java 堆一样,为线程共享。用于存储已被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据。也叫作 Non-Heap(非堆)。

如果方法区无法满足内存分配需求,会抛出 OutOfMemoryError 异常。

运行时常量池

运行时常量池是方法区的一部分。Class 文件中的常量池用于编译期生成的各种字面量和符号引用,这部分内容在类加载后被存入运行时常量池。

动态性是运行时常量池相对于 Class 文件常量池的一个重要特征,即不要求常量一定只有编译期才能产生,运行期间也可能将新的常量放入池中。

运行时常量池受到方法区内存的限制,如果常量池无法再申请内存,就会抛出 OutOfMemoryError 异常。

直接内存

直接内存并不由 JVM 管理,它是利用 Native 函数库在 Java 堆外申请分配的内存区域,可以避免在 Java 堆和 Native 堆中复制数据以提高性能。

例如 NIO 中的 DirectByteBuffer 就可以作为这块内存的引用进行操作直接内存。

永久代与元空间

有时会看到方法区被称为永久代,其实两者有着本质的区别。方法区是 JVM 规范中的定义,而永久代是 JVM 规范的一种实现,并且只有在 HotSpot 虚拟机中如此,其他虚拟机中没有永久代的说法。

JDK1.6 之前,HotSpot 虚拟机把 GC 分代收集扩展至方法区,或者说使用永久代实现方法区。不过永久代有 -XX:MaxPermSize 的上限,很容易遇到内存溢出问题。

所以在 JDK1.7 中,将部分数据已经转移 Java HeapNative Heap 中,例如:将原本放在永久代中的字符串池和类的静态变量移出到 Java Heap 中,将符号引用转移到 Native Heap 中。但永久代仍然存在,并没有移除。

JDK1.8 中,取消了永久代,代替为元空间实现,它也是 JVM 规范中方法区的一种实现。不过它与永久代最大的不同是:元空间并不在虚拟机中,而是将元空间放到本地内存中。所以默认情况下,它只受本地内存的限制,可以通过 -XX:MetaspaceSize 参数设置初始空间大小,默认没有最大空间限制。

常见的 OOM 及原因

Java 中的 OOM 指的就是 java.lang.OutOfMemoryError 异常。主要有以下几种:

java.lang.OutOfMemoryError:Java heap space

Java 堆中主要用于存放各种对象实例。当堆中没有足够的空间分配给新对象时,或者说达到了堆空间设置的最大空间限制,则会抛出此异常。

引起内存溢出的原因主要有:

  • 流量访问量大,超过设置的堆空间大小;
  • 内存泄露,不能被回收的对象消耗过多堆空间;

java.lang.OutOfMemoryError:Permgen space

JDK7 中,HotSpot 虚拟机使用永久代实现方法区,永久代较小,而且回收效率较低,很容易出现内存溢出。

因此,JDK8 取消了永久代,使用元空间来实现方法区,存放在本地内存中。

java.lang.OutOfMemoryError:Metaspace

方法区主要存储类的元信息,HotSpot 元数据区。当元空间没有足够的空间分配给加载的类时,会抛出此异常。

引起元数据区空间不足的原因主要有:

  • 加载的类太多,常见于 jsp 页面过多时;
  • 元空间被实现在堆外,主要受到进程本身的内存限制,一般很难出现溢出。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容