第二章. 自动内存管理机制

Java内存区域与内存溢出异常

java虚拟机在执行Java程序过程中会把它管理的内存划分为若干个不同的数据区域

程序计数器

  1. 程序计数器是一块较小的内存空间,它可以看作是当前线程所执行的字节码的行号指示器
  2. 程序计数器属于线程私有
  3. 当执行Java方法计器记录的是正在执行的虚拟机字节码指定的地址如果执行的是native方法,计数器的值为空
  4. 该内存区域是唯一一个在Java虚拟机规范中没有规定任何OutOfMemoryError情况的区域

Java虚拟机栈

  1. 虚拟机栈也是线程私有的,它的生命周期和线程相同
  2. 虚拟机栈描述的是Java方法执行的内存模型:每个方法在执行的同时都会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息.每一个方法的调用直至执行完成的过程,就对应这一个栈帧在虚拟机栈中入栈到出栈的过程
  3. 局部变量表保存的是各种基本数据类型、对象引用和returnAddress(执行了一条字节码指令的地址)
  4. 64为的long和double会占用两个局部变量空间,其他的数据类型只占用一个,局部变量表所需的内存空间在编译期间完成分配,当进入一个方法时,这个方法需要在帧中分配多大的局部变量空间是完全确定的,在方法运行期间不会改变局部变量表的大小
  5. 如果线程请求的栈深度大于虚拟机所准许的深度,将抛出StackOverflowError.如果虚拟机栈无法申请到足够的内存,就会抛出OutOfMemoryError

本地方法栈

  1. 本地方法栈为虚拟机使用到Native方法服务
  2. 虚拟机规范中对本地方法栈中方法使用的语言、使用方式与数据结构没有强制规定,不同的虚拟机可以自由实现
  3. 本地方法栈也会抛出StackOverflowError和OutOfMemoryError异常

Java堆

  1. Java堆是所有线程中共享的一块内存区域,在虚拟机启动时创建
  2. 此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存
  3. Java堆是垃圾收集器管理的主要区域
  4. 堆没有内存完成实例分配,并且堆也无法再扩展时,将会抛出OutOfMemoryError
  5. 堆大小可以通过-Xmx -Xms来进行配置

方法区

  1. 方法区是各个线程共享的内存区域
  2. 用于存储已被虚拟机加载的类的信息、常量、静态变量、即时编译器编译后的代码等数据
  3. 当方法区无法满足内存分配需求时,将会抛出OutOfMemoryError
运行时常量池
  1. 用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后进入方法区的运行时常量池中存放
  2. 运行期间可以将新的常量放入池中

HotSpot虚拟机对象探秘

对象的创建

首先,检查这个指令的参数是否在常量池中定位到一个类的符号引用,并检查这个符号引用代表的类是否已被加载、解析和初始化

对象的内存布局

内存中的布局可以分为3块区域:对象头、实例数据和对齐填充

对象头

对象头包括两部分: 1. 第一部分用于存储对象自身的运行时的数据 ,32bit Mark Word,25bit用于存储对象哈希码,4bit存储对象分代年龄,2bit用于存储锁标志位,1bit固定为0. 2. 另一部分是类型指针,对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是那个类的实例

实例数据

实例数据是对象真正的存储的有效信息,也是在程序代码中所定义的各种类型的字段内容,无论是从父类继承下来的,还是在子类中定义的,都需要记录起来.

对齐填充

对齐填充并不是必然存在的,也没有特别的含义,它仅仅起到占位符的作用

对象的访问定位

reference类型在Java虚拟机规范中只规定了一个指向对象的引用,目前主流的访问方式有使用句柄和直接指针两种 1. Java堆中将会划分出一块内存来作为句柄池,reference中存储的就是对象的句柄地址,而句柄中包含了对象实例数据与类型数据各自的具体地址信息 2. Java堆对象的布局需要考虑如何放置访问类型数据相关的信息,而reference中存储的就是对象地址 优缺点: 1. 使用句柄访问最大的好处就是reference中存储的是稳定的句柄地址,在对象被移动时只会改变句柄中的实例数据指针,而reference本身不需要修改 2. 直接指针访问速度更快

Java堆溢出

Java堆用于存储对象实例,只要不断地创建对象,并且保证GC Roots到对象之间有可达路径来避免垃圾回收机制清除这些对象,那么在对象数量到达最大堆的容量限制后就会产生内存溢出 1. 内存溢出,内存泄露 可以通过工具查看GC Roots的引用链来确定问题 2. 通过检查-Xmx -Xms的内存来确定问题

虚拟机栈和本地栈溢出
  1. 如果线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverflowError
  2. 如果虚拟机在扩展时无法申请到足够的内存空间,则抛出OutOfMemoryError
  3. -Xss设置栈容量大小

原创文章,转载请注明: 转载自并发编程网 – ifeve.com本文链接地址: 第二章. 自动内存管理机制


FavoriteLoading添加本文到我的收藏
  • Trackback 关闭
  • 评论 (0)
  1. 暂无评论

您必须 登陆 后才能发表评论

return top