深入理解java虚拟机-Java内存区域与内存溢出异常

运行时数据区

程序计数器

  • 程序计数器可以看做是当前线程所执行的字节码的行号指示器
  • 每条线程都有一个独立的程序计数器,属于线程私有内存
  • 此内存区域是唯一一个没有规定OOM情况的区域

Java虚拟机栈

  • 线程私有,生命周期与线程相同
  • 虚拟机栈描述的是java方法执行的内存模型.每个方法从调用到执行完成的过程.都对应这一个栈帧在虚拟机栈中的入栈和出栈
  • 栈帧是方法运行时的基础数据结构
  • 局部变量表:存放编译期可知的基本数据类型,对象引用,returnAddress类型,
  • 虚拟机执行Java方法服务

本地方法栈

  • 虚拟机使用native方法服务

Java堆

  • 线程共享
  • 垃圾回收器管理的主要区域,也被成为GC堆
  • 从分代收集算法的内存回收角度来划分
    新生代 包含:eden空间/from servivor空间 / to survivor空间
    老年代

方法区

  • 线程共享
  • 存储已被虚拟机加载到类信息,常量,静态变量,即时编译器编译后的代码

运行时常量池

  • 线程共享
  • 存储已被虚拟机加载到类信息,常量,静态变量,即时编译器编译后的代码

运行时常量池

  • 运行时常量池是方法区的一部分
  • 存放编译期生成的个中字面量和符号引用,这部分内容将在类加载后进入方法区的运行时常量池中存放.

直接内存

  • 并不是运行时数据区的一部分

hotspot虚拟机对象探秘

对象的创建

分配内存

类加载完成后便完全确定了对象所需的内存大小

指针碰撞

假设java堆中的内存都是绝对规整的,所有用过的内存都放在一边,空闲的内存放到另一边.中间放着一个指针作为分界点的指示器.那所分配的内存仅仅是把那个指针向空闲空间那边挪动一段与对象大小相等的距离.

空闲列表

Java堆不规整,已使用的内存和空闲的内存相互交错.虚拟机必须维护一个列表.记录哪块内存是可用的.在分配的时候从列表中找到一块足够大的的空间划分给对象,并更新列表上的记录

CMS收集器方式

采用CMS收集器的 通常采用空闲列表

分配内存的并发问题

CAS

采用CAS配上失败重试的方式保证原子性

TLAB

每个线程预先在Java堆中分配一块内存称为本地线程分配缓冲(TLAB),哪个线程分配内存,就在哪个线程的TLAB上进行分配. 设定: -XX:+/-UserTLAB

设置对象信息

将信息存放到对象的对象头

init

从虚拟机的角度来看,对象已经创建完成.new 指令完成 .但从java角度来看,对象创建刚刚开始,init()方法还没有执行.所有的字段都为零. 执行new指令后接着执行init指令进行初始化,这样一个对象才算完全产生.

对象的内存布局

对象头

  • 第一部分(mark word) 存储对象自身运行时数据(哈希吗.GC分代年龄,锁状态标志,线程持有的锁,偏向线程ID),
  • 第二部分类型指针,即对象指向他的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例.

实例数据

对象真正存储的有效信息.即程序代码中定义的各种类型的字段内容

对齐填充

保证对象的大小必须是8字节的整数倍

对象的访问定位

  • 句柄
    在这里插入图片描述

  • 直接指针
    在这里插入图片描述

实战:OOM异常

略.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值