杂记-几个JVM(针对HotSpot)的容易忽视的问题

前言

分享几个JVM的容易忽视的问题,但愿对你们有所帮助缓存

哪些区域会出现OOM?

Java堆溢出

  • 咱们知道,JVM参数配置中-Xms表示JVM启动时分配的内存、-Xmx表示JVM运行过程当中最大可用内存。
  • 因而可知,随着对象实例增多,超过最大堆分配内存的限制,就会出现OOM。

栈溢出

  • 栈内存容量参数由-Xss决定,而栈内存取决于栈帧数量,即栈深度,以及每一个栈帧的大小
  • 虚拟机栈常见的2种异常分为OOM以及StackOverflowError,那么,取决于什么状况,会抛相应的异常呢?

取决于栈内存是否支持扩展,HotSpot虚拟机不支持扩展jvm

  • 因为HotSpot虚拟机不支持扩展,所以OOM的发生状况:建立线程时就由于没法得到足够内存而出现OOM,建立线程时内存不足,偏偏缘由多是每一个线程的栈分配内存设置过大,在操做系统内存使用状态的影响下发生。
  • 例如,递归调用致使栈深度过大、定义大量本地变量增长栈帧中本地变量表长度,超过了-Xss所决定的栈内存容量,就会抛出StackOverflowError

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

[小插曲]方法区和常量池的关系?

  • 运行时常量池是方法区的一部分
  • 方法区存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等。
  • 运行时常量池:常量池表,用于存放编译期生成的各类字面量与符号引用。(运行时也能够将新的常量放入池中,例如String::intern()

[小插曲]方法区 == 永久代?

  • 能够说,HotSpot虚拟机使用永久代来实现方法区,这二者不等价。
  • JDK 7的HotSpot,把本来放在永久代的字符串常量池String::intern()、静态变量等移出到堆内存;JDK8彻底放弃永久代,改用本地内存的元空间(类型信息也移到了元空间)。

回归正题

  • 所以,若是使用String::intern()来制造方法区和常量池的OOM

一、JDK6或更早:字符串常量池大小增加,致使永久代的内存大小超过-XX:MaxPermSize规定的大小,致使出现PermGen space出现OOM。 二、JDK7开始,字符串常量池移入Java堆中,使用String::intern()报出OOM也是Java heap spacexss

CGLib产生大量的类填充方法区,制造OOM

  • 一、JDK7出现PermGen space出现OOM
  • 二、JDK8出现Java heap space

GC Roots指什么?

  • 虚拟机栈中引用的对象,各个线程被调用的方法中使用到的参数、局部变量、临时变量。
  • 方法区类静态属性引用的对象。
  • 方法区常量引用的对象,例如字符串常量池的引用。
  • Java虚拟机内部的引用,Class对象、异常对象、系统类加载器。
  • 同步锁持有的对象(Synchronized)。

参考

相关文章
相关标签/搜索