【JVM从小白学成大佬】2.Java虚拟机运行时数据区

  • 时间:
  • 浏览:3

这里大伙儿先说句题外话,相信大伙儿在面试中一个劲被问到介绍Java内存模型,我在面试别人时也会一个劲问你你是什么 大大问题 。否则,往往都会令我比较尴尬,我还话音未落,面试者就会“背诵”一段(Java虚拟机时有堆、依据去、虚拟机栈,吧啦吧啦。。。),估计心里还一脸自豪的想幸好哥提前在网上搜过,早有准备。每每你你是什么 原本,我全是忍心打断,导致 “背诵”的真的太顺畅了!

这也怪不得面试者,首先Java虚拟机方面的知识,对中高级应用应用程序猿来说,工作中正面接触Java虚拟机的东西如此来越多。其次,你你是什么 其次咱得好好唠唠,网上搜个Java内存模型,度娘推的第一页大全是介绍Java运行时数据区的,起到了一定的误导作用,大写的尴尬。

本篇将给各位小伙伴先完整性介绍Java运行时数据区的组成,Java内存模型也是虚拟机上面的重点,上面会单独抽出一篇来进行介绍。

1.运行时数据区介绍

应用应用应用程序所需的内存空间,某些是不到在编译期就能选者,得要在运行期根据实际运行情况报告动态地在系统中创建。Java虚拟机在执行Java应用应用程序的过程中会把它所管理的内存划分为若干个不同的数据区域。你你是什么 区域全是个人的用途,以及创建和销毁的时间,有的区域随着虚拟机应用应用程序的启动而处在,某些区域则依赖用户应用应用程序的启动和刚开始而建立和销毁。

如图所示,堆和依据区是所有应用应用程序共享的公共区域,堆和依据区所占的内存空间是由JVM负责管理的,在该区域内的内存分配是由HotSpot的内存管理模块维护的,而内存的释放工作则由垃圾分类分类整理器自动完成。虚拟机栈、本地依据栈、应用应用程序计数器是应用应用程序的私有区域,每个应用应用程序都关联着唯一的栈和应用应用程序计数器,并仅能使用属于此人 的那份栈空间和应用应用程序计算器来执行应用应用程序。

2.堆(Heap)

对于大多数应用来说,Java堆(Java Heap)是Java虚拟机所管理的内存中最大的一块。堆是可供各个应用应用程序共享的运行时内存区域,在虚拟机启动的原本就被创建。此内存区域的唯一目的只要存放对象实例,几乎所有的对象实例全是这里分配内存。你你是什么 点在Java虚拟机规范中的描述只要:所有的对象实例以及数组对象全是在堆上分配。否则随着JIT编译器的发展与逃逸分析技术逐渐心智心智成熟图片 图片 图片 是什么,栈上分配、标量替换优化技术导致 导致 某些微妙的变化处在,所有的对象都分配在堆上也渐渐变得全是如此 “绝对”了。

Java堆的容量能不到是固定的,不都能能 不到随着应用应用程序执行的需求动态扩展,并在不需用如此来越多空间时自动收缩。Java堆能不到处在物理上不连续的内存空间中,只要逻辑上是连续的即可。导致 在堆中如此 内存完成实例分配,否则堆也无法再扩展时,导致 抛出OutOfMemoryError异常。

Java堆是垃圾分类分类整理器管理的主要区域,否则好多好多 原本也被称做“GC堆”(Garbage Collected Heap)。从内存回收的厚度来看,导致 现在分类分类整理器基本都采用分代分类分类整理算法,Java虚拟机将堆划分为新生代和老年代。其中,新生代又被分为Eden区,以及有十几条 多多大小相同的Survivor区(From Survivor,To Survivor)。默认情况报告下,Java虚拟机采取的是你是什么 动态分配的策略(JVM参数-XX:+UsePSAdaptiveSurvivorSizePolicy),根据生成对象的数率,以及Survivor区的使用情况报告,动态调整Eden区和Survivor区的比例。不都能能 不到通过参数(SurvivorRatio)来调整你你是什么 比例,SurvivorRatio你你是什么 参数只要新生代中Eden区与Survivor区的容量比值,默认是8,代表Eden:Survivor=8:1。

有无导致 有十几条 多多多对象共用一段内存的事故?

当调用new指令时,会在Eden区划出一块作为存储对象的内存。导致 堆空间是应用应用程序共享的,否则直接在这上面划空间是需用进行同步的。否则,将有导致 出先有十几条 多多对象共用一段内存的事故。避免依据只要,Java堆中导致 划出多个应用应用程序私有的分配缓冲区TLAB(Thread Local Allocation Buffer,对应的虚拟机参数-XX:+UseTLAB,默认开启)。

具体来说,每个应用应用程序能不到向Java虚拟机申请一段连续内存,比如2048字节,作为应用应用程序私有的TLAB。你你是什么 操作需用加锁,应用应用程序需用维护有十几条 多多指针(实际上导致 更多,但重要也就有十几条 多多),有十几条 多多指向TLAB中空余内存的起始位置,有十几条 多多则指向TLAB末尾。接下来的new指令,便能不到直接通过指针加法(bump the pointer),全是人叫做指针碰撞来实现,即把指向空余内存位置的指针打上去所请求的字节数。导致 加法后空余内存指针的值仍小于或等于指向末尾的指针,则代表分配成功。否则,TLAB导致 如此 足够的空间来满足本次新建操作。你你是什么 原本,便需用当前应用应用程序重新申请新的TLAB。

3.依据区(Method Area)

依据区与堆一样是应用应用程序共享的,在虚拟机启动的原本创建,依据区可视为堆的有十几条 多多逻辑要素,否则它却有十几条 多多多别叫安做Non-Heap(非堆),目的应该是与Java堆区分开来。

依据区你是什么 于传统语言编译后的代码存储区域,它存储每个类的形态学 信息,如:

  • 常量池
  • 依据数据
  • 依据和构造函数的字节码
  • 类、实例、接口初始化时用到的特殊依据

备注:《深入理解Java虚拟机》里将依据区归纳为用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。

Java虚拟机规范对依据区的限制非常宽松,除了和Java堆一样不需用连续的内存和能不到选者固定大小导致 可扩展外,还能不到选者不实现垃圾分类分类整理。这区域的内存回收目标主只要针对常量池的回收和对类型的卸载。

4.应用应用程序计数器(Program Counter Register)

Java虚拟机能不到支持多条应用应用程序同時 执行,每第每根Java虚拟机应用应用程序全是此人 的应用应用程序计数器。在任意时刻,第每根Java虚拟机应用应用程序只会执行有十几条 多多依据的代码,你你是什么 正在被应用应用程序执行的依据称为该应用应用程序的当前依据(current methon)。导致 你你是什么 依据全是native的,那应用应用程序计数器保存的只要Java虚拟机正在执行的字节码指令的地址。导致 该依据是native依据,那应用应用程序计数器的值为空(undefined)。应用应用程序计数器的容量至少应当保存有十几条 多多returnAddress类型的数据导致 有十几条 多多与平台相关的本地指针的值。

应用应用程序计数器是一块较小的内存空间,它能不到看作是当前应用应用程序所执行的字节码的行号指示器。此内存区域是唯有十几条 多多在Java虚拟机规范中如此 规定任何OutOfMemoryError情况报告的区域。

5.虚拟机栈(VM Stack)

每第每根Java虚拟机应用应用程序全是此人 私有的Java虚拟机栈,它的生命周期与应用应用程序相同。虚拟机栈描述的是Java依据执行的内存模型:每个依据在执行的同時 都会创建有十几条 多多栈帧(stack frame)用于存储局部变量表、操作数栈、动态链接、依据出口等信息。每有十几条 多多依据从调用直至执行完成的过程,就对应着有十几条 多多栈帧在虚拟机栈中入栈到出栈的过程。

Java虚拟机栈导致 处在如下异常情况报告:

  • 导致 应用应用程序请求分配的栈容量超过Java虚拟机栈允许的最大容量,Java虚拟机导致 抛出有十几条 多多StackOverflowError异常。
  • 导致 Java虚拟机栈能不到动态扩展,否则在尝试扩展的原本无法申请到足够的内存,导致 在创建新的应用应用程序时如此 足够的内存区创建对应的虚拟机栈,那Java虚拟机导致 抛出有十几条 多多OutOfMemoryError异常

6.本地依据栈(Native Method Stack)

本地依据栈与虚拟机栈所发挥的作用是非常你是什么 的,它们之间的区别不过是虚拟机栈为虚拟机执行Java依据(也只要字节码)服务,而本地依据栈则为虚拟机使用到的native依据服务。

Java虚拟机规范允许本地依据栈实现成固定大小导致 根据计算来动态扩展和收缩。导致 采用固定大小的本地依据栈,如此 每有十几条 多多应用应用程序的本地依据栈容量能不到在创建栈的原本独立选定。

与虚拟机栈一样,本地依据栈区域也会抛出StackOverflowError和OutOfMemoryError异常。

7.扩展知识点

7.1 栈上分配和逃逸分析

在栈中分配的基本思路是原本的:分析局部变量的作用域仅限于依据结构,则JVM直接在栈帧内分配对象空间,避免在堆中分配。你你是什么 分析过程称为逃逸分析(全是叫逸出分析),而栈帧内分配对象的依据称为栈上分配

原本做的目的是减少新生代的分类分类整理次数,间接提高JVM性能。虚拟机是允许堆逃逸分析开关进行配置的,从Sun Java 6u23原本,HotSpot默认开启逃逸分析。

7.2 栈帧

栈帧是用于支持虚拟机进行依据调用和依据执行的数据形态学 ,它是虚拟机运行时数据区中的虚拟机栈的栈元素。栈帧存储了依据的局部变量表、操作数栈、动态连接和依据返回地址等信息每有十几条 多多依据从调用刚开始至执行完成的过程,都对应着有十几条 多多栈帧在虚拟机栈上面从入栈到出栈的过程。

在编译应用应用程序代码的原本,栈帧中需用多大的局部变量表,多深的操作数栈都导致 完整性选者了,否则写入到依据表的Code属性之中。否则有十几条 多多栈帧需用分配十几条 内存,不想收到应用应用应用程序期变量数据的影响,而仅仅取决于具体的虚拟机实现。

有十几条 多多应用应用程序中的依据调用链导致 会很长,好多好多 依据都同時 处在执行情况报告。对于执行引擎来说,在活动应用应用程序中,不到处在栈顶的栈帧才是有效的,称为当前栈帧(Current Stack Frame),与你你是什么 栈帧相关联的依据称为当前依据(Current Method)。执行引擎运行的所有字节码指令都只针对当前栈帧进行操作。栈帧的概念形态学 如下:

8.运行时数据区脑图