JVM-OutOfMemoryError异常

2.1 对象的创建

Java中对象创建的过程

1.寻找new的对象对应的类

JVM遇到new的字节码指令,根据new指令去常量池的类常量池中找到要创建的对象的类,对该类执行相应的类加载过程,

2. 给对象分配内存

对新生的对象进行内存分配。分配有两种方式:假设Java堆中内存是绝对规整的,就把使用过的内存放一边,没有使用过的内存放另一边,然后在分界处设置一个指针,当给新对象分配空间的时候,就把内存指针向未使用的内存移动要new的对象的大小,假设,Java堆中的内存并不是规整的,已被使用的内存和空闲的内存相互交错在一起,那就没有办法简单地进行指针碰撞了,虚拟机就必须维护一个列表,记录上哪些内存块是可用的,在分配的时候从列表中找到一块足够大的空间划分给对象实例,并更新列表上的记录

划分内存可用区间需要考虑的问题:

对象创建在虚拟机中是非常频繁的行为,即使仅仅修改一个指针所指向的位置,在并发情况下也并不是线程安全的,可能出现正在给对象A分配内存,指针还没来得及修改,对象B又同时使用了原来的指针来分配内存的情况。解决这个问题有两种可选方案:一种是对分配内存空间的动作进行同步处理(保证内存分配的原子性);另外一种是把内存分配的动作按照线程划分在不同的空间之中进行,即每个线程在Java堆中预先分配一小块内存,称为本地线程分配缓冲(Thread Local AllocationBuffer,TLAB),哪个线程要分配内存,就在哪个线程的本地缓冲区中分配,只有本地缓冲区用完了,分配新的缓存区时才需要同步锁定。

3. 将内存空间进行初始化

内存分配完成之后,虚拟机必须将分配到的内存空间(但不包括对象头)都初始化为零值

4. 对对象进行必要的设置

对象是那个类的实例、如何找到类的原数据信息,对象的hash码、对象的GC分代年龄信息。根据虚拟机当前运行状态的不同,如是否启用偏向锁等,对象头会有不同的设置方式。

2.2 对象的内存布局

对象头部有类信息,锁信息,如果是数组的话,还是有数组信息

对象在堆中存储,可以划分为三个部分:对象头,实例数据和对其填充。

2.3 对象的访问定位

两种方式

使用句柄访问的话

使用直接指针访问

Java是第二种方式

两种方式的优势:

使用句柄访问的优势:

使用句柄来访问的最大好处就是reference中存储的是稳定句柄地址,在对象被移动(垃圾收集时移动对象是非常普遍的行为)时只会改变句柄中的实例数据指针,而reference本身不需要被修改。

使用直接指针来访问的优势:

使用直接指针来访问最大的好处就是速度更快,它节省了一次指针定位的时间开销,

2.4OutOfMemoryError异常

三种经常出现得异常:

内存溢出:创建实例对象时内存空间不够了

栈溢出:栈内压入得方法太多了,导致无法拷贝方法入栈

内存泄漏:占用内存的数据没用了,但是不释放,导致内存无法使用

如何分析Java内存,用Java自带的可视化工具

远程:可以查看远程linux上JVM的运行情况

如何进行jvm调优?

JVM的调优:发现JVM的问题,优化问题

2.4.1 Java堆溢出

Java堆用于储存对象实例,我们只要不断地创建对象,并且保证GC Roots到对象之间有可达路径来避免垃圾回收机制清除这些对象,那么随着对象数量的增加,总容量触及最大堆的容量限制后就会产生内存溢出异常。

Java堆内存的OutOfMemoryError异常是实际应用中最常见的内存溢出异常情况。出现Java堆内存溢出时,异常堆栈信息“java.lang.OutOfMemoryError”会跟随进一步提示“Java heap space”。

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

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

2)如果虚拟机的栈内存允许动态扩展,当扩展栈容量无法申请到足够的内存时,将抛出OutOfMemoryError异常。

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

方法区溢出:就是加载的类太多了,导致方法区的内存不够了然后出现了方法区的溢出。

方法区溢出错误出现的可能性较小

运行时常量池溢出:就是常量池中存放了太多字符串类型的数据,导致无法继续放入。

PS:JDK1.7中字符串常量池在方法区中,1.8版本时字符串常量池在堆中了。

2.4.4 本机直接内存溢出

操作系统多次进行I/O操作可能就会导致本机内存溢出

dump就是某时刻的运行的状态形成的文件信息

参考:

深入理解Java虚拟机(第3版),周志明,机械工业出版社

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值