JVM学习笔记——第二章 Java内存区域与内存溢出异常

运行时数据区域

所有线程共享的数据区:
  • 方法区 :
    • 别名“非堆”,用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据。
    • JDK7的HotSpot,将放在永久代的字符串常量池、静态变量等移至Java堆中。
    • JDK8后,永久代概念被完全废弃,改用本地内存中实现的元空间代替。
  • Java堆 :
    • Java世界里“几乎”所有对象实例都在这里分配内存——栈上分配、标量替换等优化手段导致对象实例并不绝对分配在堆上了。
    • Java堆中无论设计风格下的“区域”都只能存储对象的实例,将堆细分的目的只是为了更好地回收内存 或 更快地分配内存。
    • Java堆可以处于物理上不连续的内存空间中,但对于大对象(典型的如数组对象)多数虚拟机实现出于实现简单、存储高效的考虑会要求连续的内存空间。
线程隔离的数据区:
  • 虚拟机栈 :

    • 描述Java方法执行的线程内存模型,每个方法被执行时JVM会同步创建一个帧栈用于存储局部变量表、操作数栈、动态连接、方法出口等信息。
    • 每一个方法被调用直至执行完毕,对应一个帧栈在虚拟机栈中从入栈到出栈的过程。
    • 程序员们通常指的“堆栈”中的栈狭义指局部变量表:存放了各种JVM基本数据类型、对象引用、returnAddress类型。
    • 局部变量槽的概念,64位的long和double占用两个;进入一个方法时该方法被分配多少变量槽是固定的。
  • 本地方法栈 :

    • 与虚拟机栈作用类似,区别在于虚拟机栈为虚拟机执行JAVA方法服务,而本地方法栈为JVM使用本地方法提供服务。
  • 程序计数器 :

    • 记录当前线程执行的字节码行号,为了线程切换后能恢复到正确的位置。
    • 若线程执行Java方法,则计数器记录正在执行的虚拟机字节码指令的地址;若正在执行本地方法,则值为空。
JVM运行时数据区域抛出异常的情况
  • 抛出StackOverflowError
    • 虚拟机栈:线程请求的栈深度大于虚拟机所允许的深度。
    • 本地方法栈:线程请求的栈深度大于虚拟机所允许的深度。
  • 抛出OutOfMemoryError
    • 虚拟机栈:若Java虚拟机栈 容量可以动态扩展,当栈扩展时无法申请到足够的内存。
    • 本地方法栈:若本地方法栈 容量可以动态扩展,当栈扩展时无法申请到足够的内存。
    • Java堆:若Java堆中没有内存完成实例分配,且堆也无法再扩展时。
    • 方法区:无法满足新的内存分配需求时。

HotSpot在Java堆中对象分配、布局和访问全过程

对象的创建

检查该类的符号引用是否已被加载 → 分配内存空间 → 初始化零值 → 进行必要设置 → 构造函数 → 将对象入栈

对象的内存布局

对象在堆内存中的存储布局分为:对象头、实例数据、对其填充(不必要)。

对象头(Mark Word)

对象头包括两类信息:

  • 用于存储对象自身运行时数据,如哈希码、GC分代年龄、锁状态标志、线程持有锁、偏向线程ID、偏向时间戳等。
  • 类型指针,即指向该对象类型元数据的指针。
实例数据

定义的各种类型字段内容。

对象的访问定位

Java程序通过栈上的reference数据操作堆上的具体对象,定位的方式由虚拟机实现而定,主流有 使用句柄 和 直接指针。

使用句柄

Java堆中划分一块内存作为句柄池,reference存储句柄地址,句柄包含了对象实例数据(Java堆的实例池中)类型数据(方法区中)的地址信息。
优势:对象被移动时(垃圾收集时移动对象非常普遍)只会改变句柄中的实例数据,不会修改reference。

直接指针

栈中reference直接存储Java堆中的实例数据地址,类型数据的地址需要保存在对象的内存中(如对象头)。
优势:相比句柄节省一次指针定位的时间开销(从句柄指向实例数据),在Java中访问对象很普遍,因此积少成多也是一项可观的执行成本。


OOM(内存溢出)实战

P55-P66

其中虚拟机栈和本地方法栈存在由于给栈设置分配内存越大导致越容易内存溢出OOM的原理:

  • 设n为设置的栈分配内存,m为可动态扩展数量上限
  • 在32位Windows下单个进程最大内存限制2GB,则 n * m = 2GB - 最大堆容量
  • n越大,则m越小,所以更容易导致OOM
一些虚拟机参数
  • -XX:+HeapDumpOnOutOfMemoryError:让虚拟机在OOM时Dump出当前的内存堆转储快照。
  • -Xmx-Xms:堆内存的最大值、堆的最小值,设为一样则可以避免堆自动扩展
  • -Xss:栈内存容量
  • -XX:MaxPermSize-XX:PermSize:永久代内存最大值、最小值(1.8后弃用),1.6前可间接控制常量池大小
  • -XX:MaxMetaspaceSize:元空间最大值;-XX:MetaspaceSize:元空间初始空间大小,单位字节,达到该值会触发垃圾收集进行类型卸载,同时调整元空间最大值;-XX:MinMetaaspaceFreeRatio:在垃圾收集后控制最小的元空间剩余容量百分比,可减少因元空间不足导致的垃圾收集频率;XX:MaxMetaaspaceFreeRatio:在垃圾收集后控制最大的元空间剩余容量百分比。
  • -XX:MaxDirectMemorySize:直接内存容量大小,默认与Java最大堆一致。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 222,183评论 6 516
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,850评论 3 399
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 168,766评论 0 361
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,854评论 1 299
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,871评论 6 398
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,457评论 1 311
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,999评论 3 422
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,914评论 0 277
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,465评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,543评论 3 342
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,675评论 1 353
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,354评论 5 351
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 42,029评论 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,514评论 0 25
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,616评论 1 274
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 49,091评论 3 378
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,685评论 2 360

推荐阅读更多精彩内容