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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了jvm--内存区域与内存溢出异常相关的知识,希望对你有一定的参考价值。

java是一门内存动态分配、垃圾自动回收的高级编程语言。

1 运行时数据分区

技术分享

  • 方法区

    用来存储已被虚拟机加载的类信息、常亮、静态变量、即时编译后的代码等数据;在hotspot虚拟机中又被称为永久代,此外字符串常量池已经在java7版本后移除永久代。

    运行时常量池是方法区的一部分,具有动态性,用于存放编译器生成的各种字面量和符号引用。

    内存中最大的一块,用于存放对象实例,是垃圾回收的主要区域;可分为新生代、老年代,也可分为Eden空间、From Survivor空间、ToSurvivor空间。

  • 虚拟机栈

    为虚拟机执行java方法服务,描述java方法执行的内存模型,每个方法执行的同时都会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口灯信息;方法的调用到执行完成对应的就是入栈到出栈的过程。

  • 本地方法栈

    为虚拟机使用到的Native方法服务;常用的hotspot虚拟机将虚拟机栈和本地方法栈合为一。

  • 程序计数器

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

2 HotSpot虚拟机对象探秘

  2.1 对象的创建

    假设类加载步骤已完成,还需要如下过程:

    • 为新生对象分配内存  
    • 将分配的内存空间初始化为零值,不包括对象头
    • 虚拟机对对象进行必要的设置,如属于哪个实例、GC分代年龄等信息
    • 至此从虚拟机角度,对象已创建完成;但对java程序而言,还需执行<init>方法

    其中为新生对象分配内存有两种方式:其一,指针碰撞,这种情况要求堆内存绝对规整,用过的和空闲的分别存放,只需指针在空闲空间移动相应大小即可;其二,空闲列表,虚拟机维护一个记录内存状态的列表,分配的时候找到一块足够大的空间划分给对象实例,并更新记录;两种方案的选择由堆是否规整决定,堆的状态又由具体的垃圾收集器绝定。

    此外,对象创建是一个非常频繁的动作,需要采取措施保证线程安全。此处同样有两种方案可选,其一,同步分配空间,采用CAS配上失败重试的方式保证原子性操作;其二,分配动作按照线程在不同的空间进行划分,每个线程在堆中预先分配一小块内存( Thread Local Allocation Buffer,TLAB),只有当TLAB用完并分配新的TLAB时才需要同步锁。

  2.2 对象的内存布局

    在HotSpot虚拟机中,对象在内存中分为三个区域:对象头、实例数据和对齐填充。

    • 对象头分为两部分:其一,Mark Word,用于存储对象自身的运行时数据,如哈希码、GC分代年龄、锁状态标识等;其二,类型指针,指向对象的类元数据的指针,用来确定对象是哪个类的实例。如果是java数组,对象头中还有一块记录数组长度的数据,因为从数组的元数据无法确定数组的大小。
    • 实例数据,存储代码中所定义的各种类型的字段内容,包括父类继承的、子类自定义的。
    • 对齐填充,并不是必然存在,因为HotSpotVM要求对象的起始地址必须是8字节的整数倍,所以部分情况需要补齐。

  2.3 对象的访问定位

    建立对象是为了使用对象,java程序需要通过栈上的reference数据来操作对上的具体对象,目前主流方式有使用句柄、直接指针两种方式。

    • 使用句柄,优势是reference内存储的是稳定的句柄,在对象被移动时只改变句柄中的实例数据指针,而reference本身不需要改变。

       技术分享

    • 直接指针,优势是速度快,他节省了一次指针定位的时间开销,由于对象的访问非常频繁,这种方式可以提升很高效率,HotSpot采用这种方式

      技术分享

3 OutOfMemoryError异常

  • java堆溢出,抛OutOfMemoryError异常,后面提示java heap space
  • 栈溢出,如果线程请求的栈深度大于虚拟机所允许的最大深度,抛StackOverflowError异常;如果虚拟机在扩展栈时无法获取足够空间,抛OutOfMemoryError异常
  • 方法区和运行时常量溢出,抛OutOfMemoryError异常,后面提示PermGen space

 

以上是关于jvm--内存区域与内存溢出异常的主要内容,如果未能解决你的问题,请参考以下文章

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

JVM高级特性与实践:Java内存区域 与 内存溢出异常

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

JVM学习与问题总结——java内存区域与内存溢出异常

JVM:Java内存区域与内存溢出异常

深入理解JVM——Java内存区域与内存溢出异常