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

对象的创建过程:

一.现在常量池中定位符号的引用

二.是否被加载,解析或者初始化过,如果没有初始化,则执行classLoader,执行里面的static块内容等

三.从java堆中划分内存空间,有以下两种方式

    1.指针碰撞,要求内存空间是连续的。每次将指针移动需要的空间。

    2.空闲列表,内存空间可以不连续,需要有一个列表来维护哪些空间是可用的

    多线程创建对象,由于只有一个指针,所以会出现a线程已经在使用指针,b线程获取了尚未移动的指针,这样操作了相同的内存地址,就会出现问题,解决方案有二:

    1.cas(乐观锁)加上失败重试来保证更新的原子性。

    2.给每个线程都有一小块内存缓冲(Thread Local Allocation Buffer,TLAB),线程需要分配内存,先使用TALB,使用完之后同步锁定分配内存。

     内存分配完毕,给内存空间初始化零值。

    最后在new之后执行init方法,这样一个真正可用的对象才算真正初始化完毕。

对象的内存布局

    一. 对象头,它具有以下两种类型数据

        1.自身运行时的数据,hashcode,gc分代年龄,锁状态标记,线程持有锁,偏向线程id,偏向时间戳

        2.类型指针,对象指向它的类元数据。来说明他是哪个类的实例。如果是数组,还需要记录数组长度。

    二.实例部分

    存储了java对象中真正有效的内容,包含了各种类型的字段内容。按照字段来分配,如shorts/chars

    三.对齐填充

    并非必须的,只是为了凑齐8的整数倍而已

对象的访问定位

    java程序通过栈上的reference来操作堆上的具体对象,他们之间只是建立了引用关系,通常有以下两种方式来访问:

    1.句柄访问

    堆中会划分一块内存来作为句柄池,reference存储的是句柄的地址,而句柄中包含了对象实例数据与各自的具体地址信息

从这里看出来,每个对象其实只保存了它独有的变量数据,对于method存放在对象类型数据里面,也就是method里面。

另外一种方式是直接指向对象实例数据的

第一种方式,发生gc时不需要修改reference的指向,但是慢。第二种方式相反。

OOM异常的发生

1.堆溢出,内存泄漏,内存溢出

2.栈溢出

    当jvm总的内存,超过了系统分配的则会oom

    当单线程的深度超过了栈的内存,则出现StackOverflowError

3.当方法区内 class过多或者运行时常量过多,则会出现oom错误

    

    

   

 

转载于:https://my.oschina.net/vqishiyu/blog/1828538

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值