Java虚拟机 --- oom

193 阅读3分钟

oom:out of memory error

什么叫oom

oom是指没有足够的内存分配给想要使用内存的对象。

oom分类

java堆溢出

堆中存放的对象是对象实例,只要不断的创造对象并且保证对象没有被回收(gc roots可达),这样就能不断的使用堆中的内存,导致堆中空间不够,产生oom

栈溢出

java栈分为两种:虚拟机栈,本地方法栈
栈中可能有两种异常
stack overflow error:线程请求的深度大于栈的最大深度
out of memory error:栈拓展空间是获取不到足够的空间
* 栈中存放的是函数执行相关的(局部变量,函数地址,函数参数),想要人为的实现栈溢出的,就需要不停的执行方法。

虚拟机栈

虚拟机栈中存放的是Java方法执行的内存模型,每个Java方法的执行对应着一个栈帧的进栈和出栈的操作

本地方法栈

本地方法栈中存放的是类似“JAVA虚拟机栈”,但是为native方法的运行提供内存环境。

方法区和运行时常量池

运行时常量池就在方法区中,方法区中存放的是class的相关信息,如类名,访问修饰符,常量池,字段描述。如果想要方法区溢出,要产生大量的class占满方法区,可以利用反射机制。

来自远方的补充

OutOfMemoryError异常

Java堆溢出

  • 是常见的内存溢出异常情况
  • 解决异常的方法
    • 通过内存映像分析工具对Dump出来的堆转储快照进行分析
    • 主要是确定时出现了内存泄漏还是内存溢出

内存泄漏

  • 查看泄漏对象到GC Roots的引用链。找到泄漏对象时通过怎样的路径与 GC Roots相关联并导致垃圾收集器无法自动回收他们的。
  • 掌握了泄漏对象的类型信息及GC Roots引用链的信息,就可以比较准确定位出泄漏代码的位置。

内存溢出

  • 内存的对象确实还存活着
  • 检查虚拟机的堆参数,与机器物理内存对比看是否可以调大。
  • 代码上,检查某些对象生命周期过长、持有状态实践过长的情况,尝试减少程序运行期的内存消耗。

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

  • 如果线程请求的栈深度大于虚拟机所允许的最大深度,则抛出StackOverflowErroe异常
  • 如果虚拟机在扩展栈时无法申请到足够的内存空间,则抛出OutMemoryError异常
  • 对一个问题的两种描述
  • 如果时建立过多线程导致的内存溢出,在不能减少线程数或者更换64为虚拟机的情况下,就只能通过减少最大堆和减少栈容量和换取更多的线程。

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

  • 方法区用来存放class的相关信息,如类名、访问修饰符、常量池等。
  • 方法区溢出也是常见的内存溢出异常
  • 一个类要被垃圾收集器回收掉,判定条件时比较苛刻的。

本机直接内存溢出

  • 如果不指定,大小默认与Java堆最大值一样。
  • 在Heap Dump文件中不会看到明显的异常

《java虚拟机》
java内存模型 oom