一文看懂JVM内存区域分布与作用

good123
• 阅读 745

那么我们在开始介绍Java内存区域之前,我们先放一张内存区域的图,方便我们后面介绍的时候可以对照着看。

须知,本文是根据JDK8来介绍的。

一文看懂JVM内存区域分布与作用 程序计数器 首先它是线程私有的,它也称为代码的行号指示器,字节码解释器就是通过改变程序计数器的位置来确定下一行要执行的代码,它不存在OOM。

如果线程正在执行一个Java方法,那么它记录的是正在执行虚拟机字节码指令的地址,如果是一个本地方法那么它的值为空。

Java虚拟机栈 它也是线程私有的,它的声明周期和线程一致。每个线程创建时都会创建一个虚拟机栈,内部保存了一个个的栈帧,每个栈帧就对应着一次方法的调用。既然知道了虚拟机栈里面存放的是一个个的栈帧,那么也不难猜出虚拟机栈里面都存储了什么东西。

Java虚拟机栈是存在OOM的,当线程所请求的栈的深度大于虚拟机栈的深度或者虚拟机栈可以动态扩容,当栈扩展时无法申请到足够的内存时,就会抛出OOM。

虚拟机栈内部结构:一文看懂JVM内存区域分布与作用 局部变量表:

主要存储方法的参数,所有的基本类型数据和对象地址,以及返回地址类型(return address)。它以变量槽为最小的存储单位,Java虚拟机并没有规定一个变量槽占用多少内存空间,但是规定了一个变量槽可以存放一个32位以内的数据类型。如果存储的数据类型超过32位,比如long、double,那么就使用两个变量槽进行存储。

操作数栈:

操作数栈是一个先进后出的操作数栈,当一个方法刚开始执行的时候,一个新的栈帧也会随之被创建出来,这个方法的操作数栈是空的,它主要用于保存计算过程的中间结果,同时作为计算过程中变量临时的存储空间。如果被调用的方法有返回值,那么返回值将会被压入当前栈帧的操作数栈中。操作数栈并非采用索引的方式进行数据访问,而是通过入栈(push)和出栈(pop)操作来完成数据的访问。

动态链接:

大白话就是,栈帧中保存了一个方法的引用,当执行方法的时候,可以拿着这个引用到运行时常量池中找到这个方法。

动态链接的作用就是将这些方法的符号引用转换为调用方法的直接引用。

方法返回地址:

就是在方法执行结束之后,要返回下一条要执行代码位置的值,也就是程序计数器的值。

那么除了方法正常执行结束退出外,还有另外一种情况就是异常导致的方法退出,那么这种情况下是不会返回任何值的。对于抛出的异常,栈帧中不会做任何记录,但是会记录在一个异常表中。

本地方法栈 Java虚拟机栈为虚拟机执行Java方法服务,本地方法栈则为虚拟机使用到的本地方法服务。像JVM就有好多C语言写的方法,这个就需要本地方法栈来执行。

Java堆 Java堆是虚拟机中最大的一块内存空间,它被所有的线程共享,在虚拟机启动时创建。它唯一的目的就是存放对象实例。

如果面试被问到,所有的对象实例都是在堆中分配内存吗?这个时候你一定要回答,不是。

随着即时编译技术的发展进步,尤其是逃逸分析技术的日渐强大,栈上分配、变量替换等优化手段,让实例在”只在堆“中分配不再成为绝对。

Java堆是垃圾收集的主要区域,Java堆中也经常出现新生代、老年代、永久代等等,这里需要注意,这些并不是Java堆物理上的内存布局,它是作为垃圾收集器而划分一种内存布局。

方法区 方法区也是线程共享的区域,它主要用于存储被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据。

方法区它是可以被垃圾收集器进行回收的,主要针对类型的卸载和常量池的回收。

方法区也可以产生OOM,当方法区无法满足新的内存分配需求时,将抛出OutOfMemoryError异常。

运行时常量池 运行时常量池是方法区的一部分。Class文件中除了有类的版本、字段、方法、接口等信息外,还有一项信息是常量池表,它用来存储编译期生成的各种字面量和符号引用。

如果动态链接那块没看懂,那么看了运行常量池再翻回去看看是不是好理解了。 GoodMai 好买网 IT技术交易平台

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Stella981 Stella981
3年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
JVM技术总结
1.程序计数器:记录正在执行的虚拟机的字节码的指令地址。2.java虚拟机栈:每个Java方法在执行的同时会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用直至执行完成的过程,就对应着一个栈帧在Java虚拟机栈中入栈和出栈的过程。该区域可能抛出以下异常:1.当线程请求的栈深度超过最大值,会抛出
Wesley13 Wesley13
3年前
Java 进阶(一) JVM运行时内存模型
1.JVM运行时数据区域的划分a.程序计数器(ProgramCounterRegister)一块较小的内存空间,可以看作是当前线程所执行的字节码的行号指示器。每个线程拥有独立的一个计数器,如果当前执行的是Native方法,则计数器值为空。b.JVM栈(JavaVirtualMachineS
Stella981 Stella981
3年前
JVM学习第一天
程序计数器当前线程所执行的字节码的行号指示器每个线程都有自己私有的计数器native方法,计数器值为空该内存区域没有规定任何的OutOfMemoryError情况虚拟机栈Java方法执行的内存模型,用于存储局部变量标、操作数栈、动态链接、方法出口等信息虚拟机栈也是线程私有局部变量表所需的内存控件在
good123
good123
Lv1
落日熔金,暮云合璧,人在何处
文章
14
粉丝
2
获赞
7