栏目分类:
子分类:
返回
文库吧用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
文库吧 > IT > 软件开发 > 后端开发 > Java

深入理解java虚拟机-内存管理

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

深入理解java虚拟机-内存管理

数据区域

线程共享: 堆 方法区
线程私有: 虚拟机栈 本地方法栈 程序计数器

程序计数器

当前线程所执行的字节码的行号指示器
通过改变计数器的值来选取下一条需要执行的字节码指令
如果执行的是本地方法 计数器值应该为空
此内存区域没有规定OutOfMemoryError

java虚拟机栈

虚拟机栈生命周期与线程相同
其描述的是java方法执行的内存模型:每个方法被执行的时候,java虚拟机都会同步创建一个栈帧用于存储局部变量表,操作数栈,动态链接,方法出口等信息
局部变量表存的是java虚拟机的基本数据类型 对象引用(引用指针 指向句柄等) returnAddress 返回一条字节
StackOverflowError 线程请求的栈深度大于虚拟机所允许的最大深度
OutOfMemoryError 当线程无法申请到最够的内存时会抛出该异常

本地方法栈
与虚拟机发挥的作用是非常相似的 为虚拟机使用本地方法服务
对本地方法的语言没有具体的要求

Java堆
对于Javay应用程序 堆是内存管理中最大的一块
存放对象实例 和数组
java堆物理上不连续 逻辑上连续
可以设定大小 也可扩展
堆需要扩展存放数据时 内存不够 报outofMemeryError

方法区

用于存放加载的类信息 常量 静态变量 即使编译后的代码缓存等数据。
可以选择不实现垃圾回收OutOfMemeryError

运行时常量池

方法区的一部分
class文件有类的版本 字段 方法 接口等描述信息
还有一项时常量池表 用于存放编译期生成各种字面量和符号引用 在类加载完成后 放到方法区的运行时常量池

直接内存

直接内存不是虚拟机运行数据区的部分 也不是java虚拟机规范定义的内存区域 也会导致OutOfMemoryError
jdk1.4 中 新加入了NIO(new Input/Output)类,引入了一种基于通道 与缓冲区 的I/O方式,它可以使用Native函数直接分配对外内存,然后通过一些场景能显著提升性能
直接内存受本机内存的限制

对象的创建

创建对象(列外 :复制 反序列化)一个new关键字
本章对象是指简单的对象(不包括数组和Class对象等)
虚拟机遇到一条字节码new指令,首先将去检查这个指令的参数能否在常量池中定位到一个类的符号引用 并且检查符号引用的类是否已经加载 解析 和初始化过了
如果类检查通过 则开始分配内存
堆内存的分配 如果堆内存空间规整(是否规整 由垃圾收集器是否有空间压缩整理) 则是 指针碰撞
不规整堆内存则是(例如 cms 的基于清除算法的收集器)采用空闲列表

如何解决并发?
对堆内存进行同步操作--实际采用cas配上失败重试的方法 保证更新的操作的原子性
另一种方法,内存的分配动作是按照线程划分在不同的空间之中进行,即每个线程在java堆中预先分配一块内存,称为本地线程分配内存缓存(Thread Local allocation Buffer TLAB) 只有分配的缓存分配完成 分配新的缓存区 才需要同步锁定 通过-XX :+/-UserTlAB

接下来对对象进行必要的设置 例如对象是那个类的实例 如何才能找到类的元数据信息 对象的哈希码(对象的哈希码 会延后到调用Object::hashCode才计算)对象的GC年代信息 这些信息存在对象的对象头之中

接下来执行 Class文件的()方法开始执行 对象按预定的意图构造

对象的内存布局

对象的存储布局可以分为三个部分:对象头,实例数据, 对齐填充
对象头又可以分为两部分 第一类是用于存储对象自身运行时的数据 通常 32位 和 64位 官方称为 Mark Word 实际需要存储的数据多于32或64 位 mark word被设计成动态定义的数据结构 可以动态复用自己的空间
对象头的另一部分是类型指针 即对象指向它的类型元数据的指针,java虚拟机通过这个指针来确定该对象是那个类的实例。斌不是所有的对象数据会保留类型指针
如果对象是一个java数组 则对象头还会有一块记录数组长度的数据
实例部分是真正存数据的地方
hotspot虚拟机的默认分配顺序 longs/doubles ints shorts chars bytes/booleans oops(Ordinary Object Pointers,OOPs)
对齐填充 因为java虚拟机的自动内存管理要求 对象的起始地址必须是8字节的整数倍

对象的访问定位

java程序会通过栈上的reference数据来操作堆上的具体引用
具体的实现方式 主流有两种:使用句柄 和
如果使用句柄访问的话 java堆中会花费一块内存作为句柄池 reference 存储对象的句柄地址 而句柄中存储的是对象的句柄地址 而句柄包含了对象 的实例数据与数据类型各自具体的地址信息
如果使用直接访问 Java堆中对象内存布局必须考虑如何存放访问类型数据的相关信息,reference存的是堆中的对象信息
前一种方式解耦 后一种方式速度快

转载请注明:文章转载自 www.wk8.com.cn
本文地址:https://www.wk8.com.cn/it/1040935.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 wk8.com.cn

ICP备案号:晋ICP备2021003244-6号