深入理解java虚拟机-第二章阅读笔记

目录

2.2运行时数据区域

2.2.1程序计数器(Program Counter Register)

2.2.2 java虚拟机栈(Java Virtual Machine Stack)

2.2.3 本地方法栈(Native Method Stacks)

2.2.4 java堆

2.3对象的创建

2.3.1 对象的创建

2.3.2 对象的内存布局

2.3.3 对象的访问定位

2.4 实战:OutOfMemoryError 异常

2.4.1 java堆溢出

2.4.2 虚拟机栈和本地方法栈

2.4.3 方法区和运行时常量池异常

2.4.4 本机内存直接溢出


2.2运行时数据区域

2.2.1程序计数器(Program Counter Register)

定义:是一块较小的内存空间,可以看作是当前线程所执行的字节码的行号指示器。

特点:线程私有

在虚拟机的概念模型里,字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,它是程序控制流程的指示器,分支、循环、调整、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。

在多核处理器中,为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器,各条线程之间计数器互不影响,独立存储。所以称之为线程私有的内存。

 

2.2.2 java虚拟机栈(Java Virtual Machine Stack)

特点:线程私有、生命周期与线程同步;

抛出异常:StackOverflowError 栈深度溢出,OutOfMemoryError内存溢出;

虚拟机栈描述的是java方法执行的线程内存模型:每个方法被执行的时候,java虚拟机都会同步创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息。

局部变量表存放了编译期可知的各种java虚拟机基本数据类型(boolean、byte、char、short、int、float、long、double)、对象引用和返回地址(returnAddress)。这些数据在局部变量表中以局部变量槽来表示,其中64为的long和double会占用两个变量槽。所占空间在编译期就完成了分配。

2.2.3 本地方法栈(Native Method Stacks)

和虚拟机栈类似,为虚拟机使用到本地方法服务;

2.2.4 java堆

特点:线程共享(TLAB线程私有),存储对象实例,

java的对象实例和数组都是在堆上分配么?

错,逃逸分析技术日渐强大,栈上分配,标量替换

TLAB:Thread Local Allocation Buffer ,线程私有,提升对象分配时的效率

堆细分:为了更好的回收内存或者更快的分配内存;

 

2.3对象的创建

2.3.1 对象的创建

jvm遇到new指令时,首先去检测这个指令的参数能否在常量池中定位到一个类的符号引用,并检查是否已被加载、解析和初始化过。如果没有必须先执行类加载过程。

对象频繁创建如何保证线程安全?

a、同步处理,采用cas+失败重试保证原子性;

b、通过TLAB(Thread Local Allocation Buffer)本地线程分配缓冲;

内存分配完后,jvm必须将分配到的内存空间都初始化为零。

2.3.2 对象的内存布局

2.3.3 对象的访问定位

java程序通过栈上的reference 数据来操作堆上的具体对象。

主流的访问方式分有句柄和直接指针:

句柄:堆中会划分出一块内存来作为句柄池,reference存储的是句柄地址,句柄包含了对象实例数据和类型数据具体的地址信息;

优势:当对象移动时,只会改变句柄中的实例数据指针。

直接指针:reference 中存储的是对象地址; 相比句柄省了一次指针定位的时间开销。 hotspot用的直接指针。

 

2.4 实战:OutOfMemoryError 异常

2.4.1 java堆溢出

设置参数:-XX:+HeapDumpOnOutOf-MemoryError 当oom时dump当时的堆,有助于保留现场事后分析。

调试方法:

  1. 通过String.intern()方法一直往运行时常量池中添加内容;
  2. 通过创建大数组,无法创建就oom;
  3. 通过链表,让对象一直引用;

 

2.4.2 虚拟机栈和本地方法栈

栈容量只有-Xss来设定

如果线程请求的栈深度大于虚拟机所允许的最大深度,抛出StackOverflowError异常。

虚拟机是否允许栈内存动态获取?这个在规范里让虚拟机执行选择是否支持扩展;

hotspot未支持动态扩展;

jdk11 win 64 栈不能低于180k,在linux下不能低于228k;

 

2.4.3 方法区和运行时常量池异常

方法区存放:类型的相关信息,如类名、访问修饰符、常量池、字段描述、方法描述;

  • -XX:MaxMetaspaceSize:设置元空间最大值,默认-1,不限制;
  • -XX:MetaspaceSize:指定元空间的初始大小;
  • -XX:MinMetaspaceFreeRatio: 垃圾收集之后控制最小的元空间剩余容量的百分比,可以减少元空间不足导致的垃圾收集的频率;类似于hashmap的装载因子,设置这个参数,元空间就可以弹性变动;

2.4.4 本机内存直接溢出

通过-XX:MaxDirectMemorySize 来指定直接内存,不指定则默认和java堆的最大值一致

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值