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

  • 时间:
  • 浏览:18
  • 来源:极速快3_快3注册_极速快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.运行时数据区脑图