java 内存溢出 调试_java内存区域与内存溢出异常

深入理解java虚拟机jvm高级图内存

89元

(需用券)

去购买 >

2085cc52035e79f3643d943d481990a0.png

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

运行时数据区

程序计数器/PC寄存器

当前线程所执行的字节码的行号指示器

每条线程都是独立的,独立存储,线程私有内存

当线程执行一个java方法时,记录正在执行的虚拟机字节码指令地址. 若为native方法,则为空

唯一一个java虚拟机中没有规定OOM情况的区域

虚拟机栈/方法栈

每个方法在执行时都会创建一个栈帧用于存放局部变量表,操作数栈,动态链接,方法出口等信息.每一个方法从调用到完成对应这一个栈帧在虚拟机中的入栈到出栈

局部变量表:存放编译期可知的基本类型,对象的引用(引用指针,对象句柄或其它与对象相关的位置信息 非对象本身),returnAddress类型(指向了一条字节码指令的地址)

64位(long,double)会占用2个局部变量空间(slot),其余占用一个

在方法运行时不会改变大小

线程私有的,生命周期与线程保持一致

常说的栈内存指的就是虚拟机栈

异常信息:

StackOverFlowError:线程请求的栈深度大于虚拟机允许的栈深度

OutOfMemoryError:虚拟机可动态扩展,但扩展时无法申请到足够内存

本地方法栈

与虚拟机栈基本一致

区别:

仅保存Native方法信息

java堆/GC堆

存放对象实例

被所有线程共享,虚拟机启动时创建

共享总大小内存,对于每一个线程可能划分出私有的分配缓冲区

垃圾管理器主要区域,所以也被称为GC堆

因此分出年轻代(eden,survivor),老年代(old) 1:1:8

-Xms -Xmx

OOM

方法区(Non-Heap)

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

所有线程共享

在HotSpot也被称为永久代

在JDK1.7版本的HotSpot中已将放在永久代的字符串常量池移出

方法区可以不实现垃圾收集

OOM

运行时常量池

方法区 的一部分

用于存放编译期生成的字面量,符号引用,直接引用,当类加载完毕后加入

具备动态性,运行期间也可将新的常量放入池中, String.intern()

String.intern()

jDK1.6 会将实例复制到永久代,并返回这个复制的引用

JDK1.7 不在复制实例,仅在常量池中记录首次出现的实例引用

String str = "java";

String str2 = new String("java");

boolean flag = str == str2 ;

flag 是false

new String() 创建一个对象并在堆上,str2保存堆对象地址

"java“str保存的是常量池中的java地址;

OOM

直接内存

不属于运行时数据区,也不是java虚拟机规范中定义的内存区域

OOM

对象

对象的创建

1.类加载检查. 先查询参数是否在常量池中有一个类的符号引用, 检查这个符号引用代表的类是否已经被加载,解析 初始化过,如果没有 ,则需要进行相应的类加载过程

虚拟机分配内存,并初始化为0(不包含对象头)

2.1 指针碰撞,要求java堆中内存绝对规整

2.2 空闲列表

2.3 线程安全问题

2.3.1 采用CAS和失败重试机制保证更新的原子性

2.3.2 本地线程分配缓冲(TLAB)

3.虚拟机对对象进行必要设置,实例信息,元数据信息,对象hash码,GC分代信息等,这些信息在对象头中

执行init方法 代码:P45

对象的内存布局

对象头

运行时数据 Mark Word

HashCode,GC分代年龄,锁状态标示,线程持有的锁,偏向线程ID,偏向时间戳

32位:对象处于未锁定状态 25bit HashCode 4bit 分代年龄 2bit 锁标志位 1bit 固定0

类型指针

对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象时那个类的实例

实例数据

存储对象的有效信息,定义的字段内容,受到java编写顺序和虚拟机分配策略参数影响

对齐填充

非必然存在,仅仅是占位符的作用

对象的访问定位

通过栈中的reference数据来操作堆中的具体对象

直接指针 reference 中直接保存对象地址

SUN HotSpot 采用直接指针

实例数据

类型数据指针

使用句柄 reference中保存句柄地址

在堆中维护一个句柄池

实例数据指针

类型数据指针

OOM

参数设置: -verbose:gc -Xms20M -Xmx20m -Xmn10m -XX:+PrintGCDetails -XX:SurvivorRatio=8

java堆溢出

java heap space 会有dump文件 ,通过分析dump文件确定是溢出还是泄漏

泄漏: 查看GC roots 的引用链定位泄漏代码

溢出:调整物理机内存大小,查看对象的生命周期是否过长,持有状态过长, 减少程序运行期间的内存消耗

虚拟机栈和本地方法栈溢出

单线程

仅会抛出StackOverflowError

大小: 操作系统分配进程内存2G(32位 win) - Xmx(最大堆容量) - MaxPermSize(方法区) 剩余部分可大致认为是其大小

程序计数器忽略,忽略消耗

所以当无法减少运行的线程数和无法换成64位机器时,可以考虑减少堆内存和方法区的内存大小来达到提升栈内存

方法区和运行时常量池溢出

动态生成大量的class时有可能发生,常见的有:动态生成大量JSP文件,基于OSGi的应用

本机直接内存溢出

通过-XX: MaxDirectMemorySize指定,默认与堆最大值一致(-Xmx)

Heap Dump 文件中不会看见明显的异常,若OOM后Dump文件很小,程序中直接或间接使用了NIO则可能出现

高清思维导图版请关注公众号‘伊人网络’ 回复 ‘内存’ 即可领取

java 11官方入门(第8版)教材

79.84元

包邮

(需用券)

去购买 >

f0f3f55624fb396b1764d42d6df88864.png

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值