美文网首页
1.内存区域及内存溢出异常

1.内存区域及内存溢出异常

作者: Pagliacci_Joker | 来源:发表于2019-01-28 11:41 被阅读0次

    内存区域组成

    包括:
    {堆、方法区}所有线程共享数据区。在JDK8中,hotspot宣布移除PermGen内存区域,以“元数据区”(Metaspace)替代之。
    {虚拟机栈、本地方法栈、程序计数器}线程隔离数据区
    {直接内存NIO} 基于通道与缓冲区的I/O方式,使用native方法分配堆外内存。若各块内存和大于可分配内存,则报OutOfMemortyError

    JVM内存区域.jpg

    对象在JVM上创建的过程

    1.检查new指令参数能否在常量池中定位到一个类的符号引用,并检查这个符号引用代表的类是否被加载、解析、初始化过。如果没有,则进行类的加载。加载完成后,可获得对象所需的内存大小。

    2.虚拟机为新生的对象分配内存。内存规整(指针碰撞),内存不规整(空闲列表)。
    垃圾收集器是否带有压缩整理功能,决定了内存是否规整。
    Serail,ParNew等带compact过程的收集器,采用的是指针碰撞
    CMS等基于Mark-Swap算法的收集器,采用的是空闲列表

    3.解决高并发下,指针修改问题。

    CAS配上重试失败方法
    CAS 操作包含三个操作数 —— 内存位置(V)、预期原值(A)和新值(B)。 如果内存位置的值与预期原值相匹配,那么处理器会自动将该位置值更新为新值 。否则,处理器不做任何操作。无论哪种情况,它都会在 CAS 指令之前返回该 位置的值。(在 CAS 的一些特殊情况下将仅返回 CAS 是否成功,而不提取当前 值。)CAS 有效地说明了“我认为位置 V 应该包含值 A;如果包含该值,则将 B 放到这个位置;否则,不要更改该位置,只告诉我这个位置现在的值即可。”
    通常将 CAS 用于同步的方式是从地址 V 读取值 A,执行多步计算来获得新 值 B,然后使用 CAS 将 V 的值从 A 改为 B。如果 V 处的值尚未同时更改,则 CAS 操作成功。
    类似于 CAS 的指令允许算法执行读-修改-写操作,而无需害怕其他线程同时 修改变量,因为如果其他线程修改变量,那么 CAS 会检测它(并失败),算法 可以对该操作重新计算。

    本地线程分配缓存
    将内存分配的动作按照线程划分在不同的空间中进行,即每个线程在JAVA堆中预先分配一小块内存。当TLAB并分配新的TLAB时,才需要同步锁定

    4.虚拟机将对象分配到的空间,初始化为0值。

    5.对象初始化。

    对象的内存布局

    包括:
    对象头
    实例数据
    对齐填充

    对象的内存布局.png

    对象的访问定位

    通过栈上的reference来进行访问
    包括:
    句柄访问优点:对象被移动时,只会修改实例数据指针

    image.png

    直接地址访问优点:速度快,节省一次指针查找的开销。

    image.png

    相关文章

      网友评论

          本文标题:1.内存区域及内存溢出异常

          本文链接:https://www.haomeiwen.com/subject/rnaojqtx.html