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

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

栈溢出

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

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

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

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

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

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

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

String::intern()

回归正题

  • 因此,如果使用 String::intern()
    来制造方法区和常量池的 OOM

1、JDK6或更早:字符串常量池大小增长,导致永久代的内存大小超过 -XX:MaxPermSize
规定的大小,导致出现 PermGen space
出现 OOM

2、JDK7开始,字符串常量池移入Java堆中,使用 String::intern()
报出 OOM
也是 Java heap space

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

  • 1、JDK7出现 PermGen space
    出现 OOM
  • 2、JDK8出现 Java heap space

GC Roots指什么?

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

参考

  • stackoverflow.com/questions/3…
  • 深入JVM(第三版)
  • russxia.com/2018/02/08/…

原文 

https://juejin.im/post/5ea81a77f265da7bbd2f805b

本站部分文章源于互联网,本着传播知识、有益学习和研究的目的进行的转载,为网友免费提供。如有著作权人或出版方提出异议,本站将立即删除。如果您对文章转载有任何疑问请告之我们,以便我们及时纠正。

PS:推荐一个微信公众号: askHarries 或者qq群:474807195,里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多

转载请注明原文出处:Harries Blog™ » 杂记-几个JVM(针对HotSpot)的容易忽视的问题

赞 (0)
分享到:更多 ()

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址