JVM——运行时数据区

JVM的简化架构

运行时数据区

包括:程序计数器(PC寄存器)、Java虚拟机栈、Java堆、方法区、运行时常量池、本地方法栈等等。

PC 寄存器,也叫程序计数器

  • 1、JVM支持多个线程同时运行,每个线程拥有一个程序计数器,是线程私有的,用来存储指向下一条指令的地址。

  • 2、在创建线程的时候,创建相应的程序计数器。

  • 3、执行本地native方法时,程序计数器的值为undefined。

  • 4、是一块比较小的内存空间,是唯一一个在JVM规范中没有规定OutOfMemoryError的内存区域。

虚拟机栈

  • 栈是由一系列帧(Frame)组成(因此Java栈也叫做帧栈),是线程私有的。

  • 帧是用来保存一个方法的局部变量、操作数栈(java没有寄存器,所有的参数传递使用操作数栈)、常量池指针、动态链接、方法返回值等。

  • 每一次方法调用创建一个帧并压栈,退出方法的时候,修改栈顶指针就可以把栈帧中的内容销毁。

  • 局部变量表存放了编译期可知的各种基本数据类型和引用数据类型、每个slot存放32位的数据,long、double占两个槽位。

  • 栈的优点:存取速度比堆快,仅次于程序计数器。

  • 栈的缺点:存在栈中的数据太小,生存期是在编译期决定的,缺乏灵活性。

  • StackOverflowError异常:当线程请求的栈深度大于虚拟机所允许的深度;

  • OutOfMemoryError异常:如果栈的扩展时无法申请到足够的内存。

Java堆

  • 用来存放应用系统创建的对象和数组,所有线程共享Java堆。

  • GC主要管理堆空间,对分代GC来说,堆也是分代的。

  • 堆的优点:运行期动态分配内存大小,自动进行垃圾回收。

  • 堆的缺点:效率相对较慢。

方法区

  • 方法区是线程共享的,通常用来保存装载的类的结构信息。

  • 通常和元空间关联在一起,但具体的跟JVM实现和版本有关。

  • JVM规范把方法区描述为堆的一个逻辑部分,但它有一个别名称为Non-heap(非堆),应该是为了和Java堆区分开。

运行时常量池

  • 是Class文件中每个类或接口的常量池表,在运行期间的表示形式,通常包括:类的版本、字段、方法、接口等信息。

  • 运行时常量池在方法区中分配

  • 通常在加载类和接口到JVM后,就创建相应的运行时常量池。

本地方法栈

  • 在JVM中用来支持native方法执行的栈就是本地方法栈。
  • 在JVM规范中,并没有对本地方法栈的具体实现方法以及数据结构作强制规定,虚拟机可以自由实现它。在HotSopt虚拟机中直接就把本地方法栈和Java栈合二为一。

栈、堆、方法区交互关系

栈、堆、方法区交互关系

Java堆内存模型和分配

  • Java堆用来存放应用系统创建的对象和数组,所有线程共享Java堆。

  • Java堆是在运行期动态分配内存大小,自动进行垃圾回收。

  • Java垃圾回收(GC)主要是回收堆内存,对分代GC来说,堆也是分代的。

Java堆的结构

Java堆的结构

堆是JVM内存占用最大,管理最复杂的一个区域。其唯一的用途就是存放对象实例:所有的对象实例及数组都在堆上进行分配。1.7后,字符串常量池从永久代中剥离出来,存放在堆中。堆有自己进一步的内存分块划分,按照GC分代收集角度的划分。

  • 新生代用来放新分配的对象,新生代中经过垃圾回收,没有回收掉的对象,被复制到老年代中。

  • 老年代存储的对象比新生代存储的对象的年龄大的多。

  • 老年代会存储一些大对象。

  • 整个堆大小 = 新生代 + 老年代

  • 新生代 = Eden + 存活区

  • 从前的持久代用来存放Class、Method等元信息的区域,从JDK8开始去掉了,取而代之的是元空间(MetaSpace),元空间并不在虚拟机里面,而是直接使用本地内存。

对象的内存布局

对象在内存中存储的布局(这里以HotSpot虚拟机为例说明),分为:对象头、实例数据和对齐填充。

对象头包含两个部分:
  • 1、Mark Word:用于存储对象自身的运行时数据,如:HashCode、GC分代年龄、锁状态标志、线程持有的锁、偏向线程 ID、偏向时间戳等等。
  • 2、类型指针:对象指向它的类元数据的指针。
实例数据:
  • 真正存放对象实例数据的地方
对齐填充:

这部分不一定存在,也没什么特别意义,仅仅是占位符。这是因为HotSpot要求对象起始地址都是8字节的整数倍,如果不是就对齐。

对象的访问定位

  • 在JVM规范中只规定了reference类型是一个指向对象的的引用,但没有规定这个引用具体如何去定位,访问堆中对象的具体位置。

  • 因此对象的访问方式取决于JVM的具体实现,目前主流的有:使用句柄、使用指针两种方式。

  • 使用句柄
    Java堆中会划分出一块内存来做句柄池,reference中存储句柄地址,句柄中存储对象的实例数据和类元数据的地址。

通过句柄访问对象
  • 使用指针
    Java堆中会存放访问类元数据的地址,reference存储的就直接是对象的地址。
    使用指针访问对象

各自的优势

  • 句柄访问:reference中存储的是稳定的句柄地址,在对象被移动(垃圾收集时移动对象是非常普遍的行为)时只会改变句柄中的实例数据指针,而reference本身不需要修改。

  • 直接指针访问:速度快,它节省了一次指针定位的时间开销,由于对象的访问在JAVA中非常频繁,因此这类开销积少成多后也是非常可观的执行成本。

trace跟踪参数

  • -verbose:gc:打印gc简要信息

  • -XX:+PrintGC:打印gc简要信息

  • -XX:+PrintGCDetails:打印GC详细信息

  • -XX:+PrintGCTimeStamps:打印Gc发生的时间戳

  • -Xlog:gc:log/gc.log:指定GC log的位置,以文件输出

  • -XX:+PrintHeapAtGC:每一次gc后,都打印堆信息

  • -Xlog:gc+heap=debug:每一次gc后,都打印堆信息

  • -XX:+TraceClassLoading:监控类的加载

GC日志格式

  • GC发生的时间,也就是JVM从启动以来经过的秒数

  • 日志级别信息和日志类型标记

  • GC识别号

  • GC类型和说明GC的原因

  • 容量:GC前容量 —> GC后容量(该区域总容量)

  • GC持续时间、单位秒。有的收集器会有更详细的描述,比如:user表示应用程序消耗的时间,sys表示系统内核消耗的时间,real表示操作从开始到结束的时间。

Java堆的参数

  • -Xms:初始堆大小,默认为物理内存的1/64。

  • -Xmx:最大堆大小,默认物理内存1/4。

  • -Xmn:新生代大小,默认整个堆的3/8。

  • -XX:MinHeapFreeRatio:设置堆空间最小空闲比例。当对空间的空闲内存小于这个数值时,JVM便会扩展堆空间。

  • -XX:MaxHeapFreeRatio:设置堆空间的最大空闲比例。当堆空间的空闲内存大于这个数值时,便会压缩堆空间,得到一个较小的堆。

  • -XX:NewSize:设置新生代的大小。

  • -XX:NewRatio:设置老年代与新生代的比例,它等于老年代大小除以新生代大小。

  • -XX:SurviorRatio:新生代中eden区与survivior区的比例,设置为8,则两个Survior区与一个Eden区的比值为2:8,一个Survior区占整个新生代的1/10。

  • -XX:TargetSurvivorRatio:设置survivior区的可使用率。当survivior区的空间使用率达到这个数值时,会将对象送入老年代。

  • -XX:+HeapDumpOnOutOfMemoryError:OOM时导出堆到文件。

  • -XX:HeapDumpPath:导出OOM的路径。

  • -XX:OnOutOfMemoryError:在OOM时执行一个脚本。

Java栈的参数

  • -Xss:设置线程栈的大小,通常只有几百K,决定了函数调用的深度。

元空间的参数

  • -XX:MetaspaceSize:元空间GC阈值(JDK1.8)

  • -XX:MaxMetaspaceSize:最大元空间大小(JDK1.8)

  • -XX:MaxDirectMemorySize:直接内存大小,默认为最大堆空间

  • -XX:MinMetaspaceFreeRatio:在GC之后,最小的Metaspace剩余空间容量的百分比。

  • -XX:MaxMetaspaceFreeRatio:在GC之后,最大的Metaspace剩余空间容量的百分比。

内存分配与回收策略

内存分配,主要就是堆内存分配, (也有可能经过JIT编译后被拆散为标量类型并间接的栈上分配),主要分配在新生代的eden上,如果启动了本地线程分配缓冲,将按线程优先在TLAB上分配,少数情况下可能直接分配在老年代中。分配的规则不是百分百固定的。取决于垃圾收集器的组合和虚拟机的参数设置

对象优先在Eden分配

大多数情况下,对象在新生代eden区中分配,当Eden 区没有足够空间进行分配时,发起一次 minor GC。虚拟机提供-XX:+PrintGCDetails 这个收集器日志参数,来打印日志收集日志。

大对象直接进老年代

大对象:需要大量连续内存空间的java对象 如 很长的字符串和数组。-XX:PretenureSizeThreshold 设置 大于这个值的对象直接分配在老年代

长期存活的对象进入老年代

-XX:MaxTenuringThreshold 设置年龄大于多少的对象进入老年代 默认 15 对象在 survivor中每熬过一次 minorGC年龄加一岁

动态对象年龄判断

当survivor 空间中相同年龄所有对象大小综合大于survivor 空间的一半 ,年龄大于或等于该年龄的对象可以提前进入老年代,无需等到年龄达到。

空间分配担保

发生minor GC 前虚拟机 计算老年代的连续空间是否大于新生代对象总大小或历次晋升的平均大小,是就会进行 MinorGC 否则进行FullGC

参考:
https://www.cnblogs.com/lsgxeva/p/10231201.html

https://www.cnblogs.com/lfs2640666960/p/8522588.html

https://blog.csdn.net/u011080472/article/details/51321769

https://blog.csdn.net/iva_brother/article/details/87886525

http://blog.itpub.net/69906029/viewspace-2654005/

https://blog.csdn.net/zhangxm_qz/article/details/88576660

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

推荐阅读更多精彩内容