1. java内存区域与内存溢出异常

2018-11-16  本文已影响0人  一步黎明

概述

运行时数据区域

java虚拟机在运行时有包含一下几个运行时的数据区域:

程序计数器

程序计数器是一块较小的内存空间,可以看作当前线程所执行的字节码的行号指示器。
由于java的多线程是由线程的轮流切换并分配处理器执行时间的方式实现,在任何时刻只有一条线程命令在执行。
如果线程执行的java方法,计数器记录的是正在执行的虚拟机字节码指令的地址,如果执行的是native方法,计数器则为空(Undefinded),此内存区域是唯一一个在java虚拟机规范中没有规定任何OutMemoryError情况的区域。

[========]

java虚拟机栈

java虚拟机规范,在此区域有两个异常:

本地方法

本地栈与虚拟机栈区别:

java堆

方法区(别名Non-Heap非堆)

问题:
更容易遇到内存溢出问题(永久代有-X X:MaxPermSzie的上限),JDK1.7中已将永久代的字符串常量池移出。

运行时常量池(Runtime Constant Pool)

jdk1.7 之后将常量池放入堆中

直接内存

直接内存不是虚拟机运行时数据区的一部分,也不是java虚拟规范中定义的内存区域。,但是此部分也肯能导致OutOfMemoryError异常的出现

HotSpot虚拟机对象探秘

对象创建

创建对象: 虚拟机遇到new指令,检验这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已被加载、解析、和初始化过。如果没有,就必须执行相应的类加载过程。

对象内存分配:

  1. 指针碰撞,java堆中内存是规整的
  2. 空闲列表(Free List),java堆不是规整的
    分配方式由java堆是否规整决定,java堆是否规整由采用的收集器是否带压缩整理功能决定
    Serial、parNew 带Compact过程的收集器时,系统采用指针碰撞,使用CMS基于Mark-Sweep收集器时,通常采用空闲列表。
    多线程问题:
  3. 对分配内存空间的动作进行同步处理--实际虚拟机采用CAS配上失败从事的方式保证更新操作的原子性。
  4. 把内存分配的动作按照线程划分在不同的空间中进行,(本地线程分配缓冲),-XX:+/-UseTLAB 来配置是否使用TLAB参数。

对象的内存布局(待详补)

对象在内存中存储的布局可以分3个区域:对象头(Header)、实例数据(Instance Data)和对其填充(padding)。

上一篇 下一篇

猜你喜欢

热点阅读