当前位置: 首页 > news >正文

Java内存区域与内存溢出

  • 程序计数器

    程序计数器是一块较小的内存,它是线程私有的,可以看作是当前线程执行字节码的计数器。在虚拟机的概念模型中,字节码解释器就是通过这个计数器来找到下一个将要执行的指令。java中分支语句,循环,异常处理以及线程恢复都是通过程序计数器来实现的。

    由于JVM在执行线程的时候是通过CPU轮流执行各个线程的,CPU每次只能执行一个线程的某个指令。这就要求每次在切换线程的时候要能恢复到正确的指令执行位置。因此线程的程序计数器必须是线程私有的。各个线程之间互不影响,独立存储。

    如果该线程正在执行的是一个java方法,则该程序计数器的值就是该方法编译后的正在执行的当前的虚拟字节码的指令位置。如果当前线程执行的是一个native方法,则计数器值为空Undefined。该区域是虚拟机规范中未规定OutOfMemoryError情况的区域。

  • 虚拟机栈

    该区域也是线程私有的,并且其生命周期与对应线程生命周期一致。虚拟机栈描述的就是java方法执行的内存模型:每个方法在执行的时候都会在虚拟机栈上建立一个栈帧用来保存局部变量表,操作栈,动态链接,方法出口等信息。每一个方法被调用就对应着一个栈帧在虚拟机栈中从入栈道出栈的过程。

    我们看到经常有人把内存分为堆内存和栈内存。此处的栈内存就是指虚拟机栈上的局部变量表。局部变量表中存放了编译期可知的各种基本的数据类型,int,float,boolean……以及对象的引用。其中64位长的long和double类型的数会占用两个局部变量存储空间(slot)。其余的均是占用一个。局部变量表所需要的内存空间是编译期间完全确定的。运行期间不会改变大小。在java虚拟机规范中规定里对这个内存区的两种异常情况:如果线程请求的栈深度大于虚拟机允许的最大深度将抛出StackOverflowError.如果虚拟机栈可以动态扩展的话,在扩展的时候无法申请到在足够的内存,则会抛出OutOfMemoryError。

  • 本地方法栈

    同上述两个区域一样,该区域也是线程私有区域。它与虚拟机栈发挥的左右是类似的,不同的是虚拟机栈是为java方法服务的,而本地方法栈则是为java调用的本地方法服务的。本地方法栈区也会抛出同虚拟机栈相同的两个异常。

  • java堆

    java堆内存是在虚拟机启动的时候创建,所有的对象实例都保存在这个区域,包括数组。因此堆内存也是垃圾收集器的主要工作区域。如果从内存回收的角度来看,现在收集器基本上采用的都是分代收集的策略,所以java堆中还可以细分为新生代和老年代。再细致一点的话可以分为:Eden空间,FromSurvior空间,ToSurvior空间等。

  • 方法区

存储已经被虚拟机加载进来的类信息,常量,静态变量,编译后的代码,也是线程共享的。也有人称这个区域为永久代。java虚拟机规范对这一块区域的规定比较宽松,因此该区域上可以实现垃圾收集机制,也可以不实现。该区域的垃圾收集机制主要是针对常量池的回收以及对类型的卸载。该区域不需要连续的内存,并且是可扩展的,当方法区无法满足内存分配需求时候,也会抛出OutOfMemoryError

运行时常量

运行时常量池是方法区的一个部分,Class文件中除了有类的版本,字段,方法,接口描述等信息之外,还有一项信息是常量池(Constant Pool Table),用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载之后放入方法区的常量池区域。

 

 

  对象访问

Object obj = new Object();

 

假设上面这行代码出现在一个方法中,那么声明部分“Object obj”这部分语义将会反应到虚拟机栈的局部变量表中,作为一个reference类型的数据出现。而“new Object()”这部分的语义就会反应到堆内存中,形成一块存储了Object类型所有实例数据(对象中各个实例字段的数据)的结构化内存,这块内存的长度是不变的;另外对中还必须包含能查找到该对象数据类型的数据(如对象类型,父类,实现的接口,方法等)的地址信息,这些类型数据则存储在方法区域。综上所述,堆内存要存储两部分数据:(1)对象的实例数据(2)对象类型的数据的地址信息

 

由于reference类型在java虚拟机规范中没有规定这种引用该通过哪种方式去定位,因此不通的虚拟机实现的对象访问方式不一样,主要有以下两种方式:使用句柄和直接使用指针。

  • 如果是通过句柄的方式访问对象,则在java堆中就需要划分出一块内存作为句柄池,reference中存储的就是对象的句柄地址,而句柄中则包含了对象的实例数据地址信息和类型数据的地址信息。

 

      • 如果通过指针的方式访问对象,reference中则直接存储对象的地址信息

 

 

转载于:https://www.cnblogs.com/JackDesperado/p/4788906.html

相关文章:

  • 如何删除鼠标右键菜单里的打开按钮
  • Struts2的s:date标签使用详解[转]
  • JSP隐含对象(1)
  • 二级指针的思考
  • JSP隐含对象 request(2)
  • JSP实现网页计算器
  • MySQL汇总数据
  • 如何配置Tomcat的热启动
  • vncserver
  • 项目路径配置[pageContext.request.contextPath]和c标签
  • JSP隐含对象response实现文件下载的两种方式
  • JSP动态生成验证码
  • 报表性能优化方案之多种报表服务器内存修改方法
  • JSP用过滤器解决request中文乱码问题
  • Advanced R之编程风格
  • Git的一些常用操作
  • iOS | NSProxy
  • isset在php5.6-和php7.0+的一些差异
  • java正则表式的使用
  • Linux CTF 逆向入门
  • Logstash 参考指南(目录)
  • MQ框架的比较
  • Promise面试题,控制异步流程
  • supervisor 永不挂掉的进程 安装以及使用
  • Vultr 教程目录
  • Webpack 4 学习01(基础配置)
  • 百度地图API标注+时间轴组件
  • 从伪并行的 Python 多线程说起
  • 如何设计一个微型分布式架构?
  • 我这样减少了26.5M Java内存!
  • 运行时添加log4j2的appender
  • SAP CRM里Lead通过工作流自动创建Opportunity的原理讲解 ...
  • 宾利慕尚创始人典藏版国内首秀,2025年前实现全系车型电动化 | 2019上海车展 ...
  • # 透过事物看本质的能力怎么培养?
  • #Z2294. 打印树的直径
  • (14)学习笔记:动手深度学习(Pytorch神经网络基础)
  • (4) PIVOT 和 UPIVOT 的使用
  • (6)STL算法之转换
  • (Redis使用系列) SpringBoot 中对应2.0.x版本的Redis配置 一
  • (zt)最盛行的警世狂言(爆笑)
  • (二十五)admin-boot项目之集成消息队列Rabbitmq
  • (附源码)springboot社区居家养老互助服务管理平台 毕业设计 062027
  • (附源码)计算机毕业设计SSM基于java的云顶博客系统
  • (三)centos7案例实战—vmware虚拟机硬盘挂载与卸载
  • (十) 初识 Docker file
  • (十七)Flask之大型项目目录结构示例【二扣蓝图】
  • (一)ClickHouse 中的 `MaterializedMySQL` 数据库引擎的使用方法、设置、特性和限制。
  • (已解决)报错:Could not load the Qt platform plugin “xcb“
  • (原創) 如何使用ISO C++讀寫BMP圖檔? (C/C++) (Image Processing)
  • (转)Oracle 9i 数据库设计指引全集(1)
  • (最全解法)输入一个整数,输出该数二进制表示中1的个数。
  • *(长期更新)软考网络工程师学习笔记——Section 22 无线局域网
  • *上位机的定义
  • .desktop 桌面快捷_Linux桌面环境那么多,这几款优秀的任你选
  • .helper勒索病毒的最新威胁:如何恢复您的数据?