avatar

目录
深入理解Java虚拟机(2):Java内存区域与内存溢出异常

第二部分:自动内存管理机制。包括2-5章

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

2.1 概述

– 虚拟机自动内存管理机制

– Java程序员把内存控制的权力交给了Java虚拟机

本章从概念上介绍Java虚拟机内存的各个区域

2.2 运行时数据区域

Java虚拟机运行时数据区:

![屏幕快照 2018-11-13 下午1.10.09](20181113130255132/屏幕快照 2018-11-13 下午1.10.09.png)

1、程序计数器

行号指示器;线程私有;没有规定任何OutOfMemoryError情况的区域

2、Java虚拟机栈

线程私有;

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

虚拟机栈中局部变量表存放了

  • 各种基本数据类型

  • 对象引用

  • returnAddress类型(指向了一条字节码指令的地址)

局部变量表所需的内存空间在编译期间完成分配,局部变量空间是完全确定的,不会改变。

该区域有2种异常:

  • StackOverflowError:线程请求的栈深度大于虚 拟机所允许的深度
  • OutOfMemoryError:虚拟机栈扩展时无法申请到足够的内存

3、本地方法栈

与虚拟机栈所发挥的作用是非常相似;

本地方法栈则为虚 拟机使用到的Native方法服务;

也会抛出StackOverflowError和OutOfMemoryError异常;

4、Java堆

线程共享,在虚拟机启动时创建;

目的:存放对象实例;

也被称做“GC堆”(Garbage Collected Heap),是垃圾收集器管理的主要区域;

Java堆中可能划分出多个线程私有的分配缓冲区(Thread Local Allocation Buffer,TLAB);

5、方法区

线程共享;

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

别名叫做Non-Heap(非堆);

当方法区无法满足内存分配需求时,将抛出 OutOfMemoryError异常

运行时常量池: (Runtime Constant Pool)是方法区的一部分

用于 : Class文件常量池存放编译期生成的各种 字面量和符号引用,这部分内容将在类加载后进入方法区的运行时常 量池中存放;

运行时常量池相对于Class文件常量池的另外一个重要特征是具备动态性;

受到方法区内存的限制,当常量池无法再申 请到内存时会抛出OutOfMemoryError异常;

6、直接内存

并不是虚拟机运行时数据区的一部分;

使用Native函数库直接分配堆外内存(NIO(New Input/Output)类);

动态扩展时出现OutOfMemoryError异常(经常忽略 直接内存,使得各个内存区域总和大于物理内存限制);

2.3 HotSpot虚拟机对象探秘

虚拟机中对象的创建过程(new指令):

1、确保常量池中存放的是已解释的类

2、确保对象所属类型已经经过初始化阶段(否则必须先执行相应的类加载过程)

3、为新对象分配内存

​ 如何划分可用空间?

​ –内存规整:指针碰撞

​ –内存不规整:空闲列表

​ 如何保证并发下的线程安全?

​ –同步处理:CAS+失败重试保证原子性

​ –本地线程分配缓冲(Thread Local Allocation Buffer,TLAB):按照线程划分在不同的空间

4、为对象初始化零值

5、设置对象头信息

6、将对象引用入栈

7、执行new指令之后(所有的字段都还为零)会接着 执行<init>方法(把对象按照程序员的意愿进行初始化)

文章作者: Machine
文章链接: https://machine4869.gitee.io/2018/11/13/20181113130255132/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 哑舍
打赏
  • 微信
    微信
  • 支付宝
    支付宝

评论