JVM系列(2)-对象和OOM异常


上一讲中,我们了解了JVM的内部结构,更准确的讲应该是JVM运行时数据区,知道了对象的实例是在堆中分配的。那到底是怎么创建的,都有哪些信息需要创建,我们今天就先讲下这个,以Hotspot实现为例。



问题1:对象是怎么创建的?


我们创建对象的时候,会使用new关键字,像这样:Object obj = new Object();虚拟机在遇到new这个关键字的时候,会先检查这个类有没有被加载。如果没有,则需要先加载这个类;如果已经加载,则为对象分配内存。至于需要划分多大的堆内存,类加载完成后,这个大小就确定了,这也是为什么要在分配内存前,先确保类已加载;因为只有加载后,才知道需要分配多大内存。


需要分配的内存大小确定了,那就划分一块内存呗,但这里又有几个问题。

1)JVM的堆内存是规整的,还是凌乱的?

规整的就是,已经使用过的堆内存和没有使用的堆内存有一个明确的分界线。像下面这样,要分配新内存时,直接在空闲区划拉一块儿。专业的叫法是“指针碰撞”。




如果是不规整的,像下面这样,就需要一个列表来记录,记录哪些是空闲的。这种方式称作“空闲列表”。


2)并发情况下,在线程1尝试分配对象A内存时,还没来得及分配,就让出了CPU和时间片,此时,线程2执行,尝试分配对象B内存,使用的是相同的指针(分配的起始地址)。这就有问题了。

解决方法

i>采用同步方法处理分配内存的动作;

ii>TLAB(Thread Local Allocation Buffer),对每个线程,预先在堆中分配一块儿内存,每个线程,首先在自个儿的这个区间分配内存,在消耗完之后,再做同步处理。


-XX:+/-UseTLAB控制JVM是否采用TLAB这种方式。


对象创建后,在内存中都记录了哪些信息?我们继续往下看。


问题2:对象的内存布局



对象内存区域分3个,对象头 + 实例数据 + 对齐填充。

对象头又包括运行时数据 + 类型指针。


有没有想过对象的类型信息是存在哪儿的?如下图,类型信息存在方法区。


问题3:OutOfMemoryError异常



JVM运行时数据区包括方法区 + 堆 + 虚拟机栈 + 本地方法栈 + 程序计数器。除了程序计数器不会抛出异常外,其他的区域都有可能抛出OOM Error。

1) 堆

JVM通过-Xmx和-Xms参数控制堆大小

2)栈

JVM通过-Xoss和-Xss参数控制栈的大小

3)方法区

JVM通过-XX:PermSize和-XX:MaxPermSize参数控制大小


这块儿简单讲了下,明天讲下垃圾收集和内存分配。





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值