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

  • 时间:
  • 浏览:1
  • 来源:幸运快3_快3app开户_幸运快3app开户

这里朋友 先说句题外话,相信朋友 在面试中老是被问到介绍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区,以及另另4个大小相同的Survivor区(From Survivor,To Survivor)。默认请况下,Java虚拟机采取的是两种动态分配的策略(JVM参数-XX:+UsePSAdaptiveSurvivorSizePolicy),根据生成对象的下行波特率 ,以及Survivor区的使用请况,动态调整Eden区和Survivor区的比例。都还里能都还里能通过参数(SurvivorRatio)来调整你一些比例,SurvivorRatio你一些参数很多 新生代中Eden区与Survivor区的容量比值,默认是8,代表Eden:Survivor=8:1。

与否完后 有另另4个对象共用一段内存的事故?

当调用new指令时,会在Eden区划出一块作为存储对象的内存。完后 堆空间是系统进程共享的,否则直接在这上方划空间是还要进行同步的。否则,将有完后 再次冒出另另4个对象共用一段内存的事故。外理法子很多 ,Java堆中完后 划出多个系统进程私有的分配缓冲区TLAB(Thread Local Allocation Buffer,对应的虚拟机参数-XX:+UseTLAB,默认开启)。

具体来说,每个系统进程能都还里能向Java虚拟机申请一段连续内存,比如2048字节,作为系统进程私有的TLAB。你一些操作还要加锁,系统进程还要维护另另4个指针(实际上完后 更多,但重要也就另另4个),另另4个指向TLAB中空余内存的起始位置,另另4个则指向TLAB末尾。接下来的new指令,便能都还里能直接通过指针加法(bump the pointer),与否人叫做指针碰撞来实现,即把指向空余内存位置的指针添加所请求的字节数。完后 加法后空余内存指针的值仍小于或等于指向末尾的指针,则代表分配成功。否则,TLAB完后 这么 足够的空间来满足本次新建操作。你一些完后 ,便还要当前系统进程重新申请新的TLAB。

3.法子区(Method Area)

法子区与堆一样是系统进程共享的,在虚拟机启动的完后 创建,法子区可视为堆的另另4个逻辑部分,否则它却有另另4个别叫兰做Non-Heap(非堆),目的应该是与Java堆区分开来。

法子区类似于于传统语言编译后的代码存储区域,它存储每个类的形态学 信息,如:

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

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

Java虚拟机规范对法子区的限制非常宽松,除了和Java堆一样不还要连续的内存和能都还里能选着固定大小完后 可扩展外,还能都还里能选着不实现垃圾架构设计 。这区域的内存回收目标主很多 针对常量池的回收和对类型的卸载。

4.系统进程计数器(Program Counter Register)

Java虚拟机能都还里能支持多条系统进程一起去执行,根小小Java虚拟机系统进程与否当事人的系统进程计数器。在任意时刻,根小Java虚拟机系统进程只会执行另另4个法子的代码,你一些正在被系统进程执行的法子称为该系统进程的当前法子(current methon)。完后 你一些法子与否native的,那系统进程计数器保存的很多 Java虚拟机正在执行的字节码指令的地址。完后 该法子是native法子,那系统进程计数器的值为空(undefined)。系统进程计数器的容量相当于应当保存另另4个returnAddress类型的数据完后 另另4个与平台相关的本地指针的值。

系统进程计数器是一块较小的内存空间,它能都还里能看作是当前系统进程所执行的字节码的行号指示器。此内存区域是唯一另另4个在Java虚拟机规范中这么 规定任何OutOfMemoryError请况的区域。

5.虚拟机栈(VM Stack)

根小小Java虚拟机系统进程与否当事人私有的Java虚拟机栈,它的生命周期与系统进程相同。虚拟机栈描述的是Java法子执行的内存模型:每个法子在执行的一起去与否创建另另4个栈帧(stack frame)用于存储局部变量表、操作数栈、动态链接、法子出口等信息。每另另4个法子从调用直至执行完成的过程,就对应着另另4个栈帧在虚拟机栈中入栈到出栈的过程。

Java虚拟机栈完后 指在如下异常请况:

  • 完后 系统进程请求分配的栈容量超过Java虚拟机栈允许的最大容量,Java虚拟机完后 抛出另另4个StackOverflowError异常。
  • 完后 Java虚拟机栈能都还里能动态扩展,否则在尝试扩展的完后 无法申请到足够的内存,完后 在创建新的系统进程时这么 足够的内存区创建对应的虚拟机栈,那Java虚拟机完后 抛出另另4个OutOfMemoryError异常

6.本地法子栈(Native Method Stack)

本地法子栈与虚拟机栈所发挥的作用是非常类似于的,它们之间的区别不过是虚拟机栈为虚拟机执行Java法子(也很多 字节码)服务,而本地法子栈则为虚拟机使用到的native法子服务。

Java虚拟机规范允许本地法子栈实现成固定大小完后 根据计算来动态扩展和收缩。完后 采用固定大小的本地法子栈,这么 每另另4个系统进程的本地法子栈容量能都还里能在创建栈的完后 独立选定。

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

7.扩展知识点

7.1 栈上分配和逃逸分析

在栈中分配的基本思路是完后 的:分析局部变量的作用域仅限于法子內部,则JVM直接在栈帧内分配对象空间,外理在堆中分配。你一些分析过程称为逃逸分析(与否叫逸出分析),而栈帧内分配对象的法子称为栈上分配

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

7.2 栈帧

栈帧是用于支持虚拟机进行法子调用和法子执行的数据形态学 ,它是虚拟机运行时数据区中的虚拟机栈的栈元素。栈帧存储了法子的局部变量表、操作数栈、动态连接和法子返回地址等信息每另另4个法子从调用现在结速至执行完成的过程,都对应着另另4个栈帧在虚拟机栈上方从入栈到出栈的过程。

在编译系统进程代码的完后 ,栈帧中还要多大的局部变量表,多深的操作数栈都完后 完全选着了,否则写入到法子表的Code属性之中。否则另另4个栈帧还要分配几条内存,无需收到系统进程运行期变量数据的影响,而仅仅取决于具体的虚拟机实现。

另另4个系统进程中的法子调用链完后 会很长,很多有法子都一起去指在执行请况。对于执行引擎来说,在活动系统进程中,都还里能指在栈顶的栈帧才是有效的,称为当前栈帧(Current Stack Frame),与你一些栈帧相关联的法子称为当前法子(Current Method)。执行引擎运行的所有字节码指令都只针对当前栈帧进行操作。栈帧的概念形态学 如下:

8.运行时数据区脑图