第二章 Java内存区域与内存溢出异常

运行时数据区域

程序计数器(Program Counter Register)

程序计数器:当前线程所执行的字节码行号指示器.各条线程之间计数器互不影响,独立存储.也称之为"线程私有"的内存.

PS:当执行Native方法时,计数器值为空(Undefined).此内存区域是唯一一个在Java虚拟机规范中没有规定任何OutOfMemoryError情况的区域.

Java虚拟机栈(Java Virtual Machine Stacks)

​ 描述的是Java方法执行的内存模型:每个方法在执行的同时都会创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。

局部变量表

​ 存放了编译期可知的各种基本数据类型(boolean、byte、char、short、int、float、long、double)、对象引用(reference类型,它不等同于对象本身,可能是一个指向对象起始地址的引用指针,也可能是指向一个代表对象的句柄或其他与此对象相关的位置)和returnAddress类型(指向了一条字节码指令的地址)

StackOverflowError异常

​ 线程请求的栈深度大于虚拟机所允许的深度

OutOfMemoryError异常

​ 虚拟机栈可以动态扩展(当前大部分的Java虚拟机都可动态扩展,只不过Java虚拟机规范中也允许固定长度的虚拟机栈),如果扩展时无法申请到足够的内存.

本地方法栈(Native Method Stack)

​ 与虚拟机栈的区别在于,本地方法栈执行的是Native方法.

Java堆(Java Heap)

​ Java堆被所有线程共享,在虚拟机启动时创建.用于存放对象实例:所有的对象实例以及数组都要在堆上分配(并不绝对).

​ 划分:新生代和老年代.

​ 再细致一点的有Eden空间、From Survivor空间、To Survivor空间等.

方法区(Method Area)

​ 线程共享.

​ 用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据

运行时常量池(Runtime Constant Pool)

​ 方法区的一部分.

  • 常量池(Constant Pool):常量池数据编译期被确定,是Class文件中的一部分。存储了类、方法、接口等中的常量,当然也包括字符串常量。
  • 字符串池/字符串常量池(String Pool/String Constant Pool):是常量池中的一部分,存储编译期类中产生的字符串类型数据。
  • 运行时常量池(Runtime Constant Pool):方法区的一部分,所有线程共享。虚拟机加载Class后把常量池中的数据放入到运行时常量池。

对象的创建

new -> 检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并检查这个符号引用代表的类是否已被加载、解析和初始化过。若没有,则必须执行相应的类加载过程。-> 虚拟机为新生对象分配内存。

PS:从虚拟机的视角来看,一个新的对象已经产生了,但从Java程序的视角来看,对象创建才刚刚开始——<init>方法还没有执行,所有的字段都还为零。所以,一般来说(由字节码中是否跟随invokespecial指令所决定),执行new指令之后会接着执行<init>方法,把对象按照程序员的意愿进行初始化,这样一个真正可用的对象才算完全产生出来。

对象的内存布局

    HotSpot虚拟机中,布局可分为三块区域:对象头(Header)、实例数据(Instance Data)和对齐填充(Padding)。

对象头

  • 存储对象自身的运行时数据如哈希码、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等
  • 存储类型指针,即对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例(并不是所有的虚拟机实现都必须在对象数据上保留类型指针)。

实例数据

    对象真正存储的有效信息,即定义的各种类型的字段内容(包括继承而来的)。

对齐填充

   不必须存在。仅仅作为占位符。因为HotSpot虚拟机要求对象起始地址必须是8字节的整数倍。因此当实例数据部分没有对齐时,就需要对齐填充。

对象的访问定位

​ 通过栈上的reference数据来操作堆上的具体对象。主流访问方式也有如下两种:

  • 句柄:

    优势在于reference中存储的是稳定的句柄地址。

  • 直接指针(Hotspot采用)

    优势在于访问对象速度更快。

最新文章

  1. 4_jquery
  2. WIN7 IIS7 安装方法
  3. windows 程序设计自学:添加图标资源
  4. 汉字编码:GB2312, GBK, GB18030, Big5
  5. SQL Server Object Explorer in VS
  6. 解决 Ubuntu 开机 Waiting for 60 seconds more for network configuration
  7. 用PC浏览器模拟手机浏览器(一):无扩展版
  8. volatile--共享数据必须保证可见性
  9. bzoj 2631: tree 动态树+常数优化
  10. java——输入流FileInputStream
  11. map的类型映射
  12. poj3581Sequence(后缀数组)
  13. 恢复PasswordChar 默认值、取消密码框设置
  14. android 请求接口报错 org.apache.http.conn.HttpHostConnectException: Connection to http://192.168.1.90:9090 refused
  15. Spring Boot:The field file exceeds its maximum permitted size of 1048576 bytes
  16. eclipse Android项目 DDMS db文件 导出 Failed to pull selection null 问题
  17. Kaldi阅读并更改代码
  18. Java——Struts2 crud 简单实例(学习struts2和ssh) 用Myeclipse实现
  19. 关于Java Web应用中的配置部署描述符web.xml
  20. C++中多态中构造函数与析构函数的调用

热门文章

  1. ASP.NET CORE MVC 2.0 如何在Filter中使用依赖注入来读取AppSettings,及.NET Core控制台项目中读取AppSettings
  2. 系统优化怎么做-Linux系统配置优化
  3. python 输入三个整数,按照从小到大的顺序打印
  4. DB数据源之SpringBoot+MyBatis踏坑过程(四)没有使用连接池的后果
  5. HTML5中的拖拽与拖放(drag&&drop)
  6. Java性能优化的50个细节
  7. .Net Core如何在程序的任意位置使用和注入服务
  8. numpy如何使用
  9. Java使用zxing生成解读QRcode二维码
  10. 『Python基础-5』数字,运算,转换