Java虚拟机-内存区域

时间:2022-12-27 13:47:35

jvm内存区域

方法区(Method Area) 常量池(Run-Time Constant Pool) 堆(Heap
程序计数器(Program Counter) 虚拟机栈(Java Virtual Machine Statcks) 本地方法栈(Native Method Stacks)

方法区(Method Area)

存储class类型、常量、静态变量、即时编译后的代码等数据。各个线程共享区域。

常量池(Run-Time Constant Pool):常量池属于方法区,存储常量和在编译期生成的各种字面量和符号引用。

可能抛异常:

OutOfMemeoryError

原因

如果需要在方法区(PermGen)申请分配内存请求时,此时方法区(PermGen)内存不够,则抛出OutOfMemoryError。

通常是:

  • jsp页面或通过CGLib、OSGI动态生成大量的类,有可能导致PermGen space内存不足。
  • 是由于使用String.intern()方法添加了过多内容。

解决方法:

  • 检查是否使用String.intern()添加了过多内空,
  • 增大 -X:MaxPermSize 参数值。class也可以回收的,参数:-XX:+UseConcMarkSweepGC -XX:+CMSClassUnloadingEnabled 。但不建议这样种。

堆(Heap)

存储所有对象和数组实例。

可能抛异常

OutOfMemeoryError

原因

当jvm评估需要申请的内存超过jvm堆最大内存时,抛OutOfMemoryError。

解决方法

  • 检查程序是否有死循环
  • 检查程序是否存在资源未释放
  • 检查程序是否瞬间申请大量内存
  • 增大堆大小。参数: -Xmx

程序计数器(Program Counter)

记录正在执行的虚拟机字节码指令的地址。每个线程都有自已独立的区域。

虚拟机栈(Java Virtual Machine Statcks)

存储局部变量表(基本数据类型)、操作栈、动态链接、方法出口等信息。

可能抛异常

StockOverflowError、OutOfMemeoryError

原因

  • StockOverflowError: 可能是线程请求的栈深度超出虚拟机允许的最大深度。
  • OutOfMemeoryError: 可能是多线程环境在创建新线程时申请栈空间时内存不足。

解决方法

对于StockOverflowError异常,需检查程序是否有递归调用次数过多。
对于OutOfMemeoryError 异常,则需要根据系统情况调整参数-Xss参数。

总结公式:

-Xss = (操作系统剩余内存 - (-Xmx) - (-X:MaxPermSize) - 本地方法栈 ) / 预计的线程数

本地方法栈(Native Method Stacks)

C Statck,存储native方法本地变量、操作栈等信息。

可能抛异常

StockOverflowError、OutOfMemeoryError。

原因

  • *Error:
    如果一个线程申请一个很大的本地方法栈时,超过了最大限制则抛*Error。

  • OutOfMemoryError:
    如果本地方法栈可以动态扩展,并且本地方法栈申请扩展更多内存,但此时系统内存不足;或者是当在创建一个新的线程时,无法申请到初始化本地方法栈的内存时抛OutOfMemoryError。

解决方法

  • *Error :控制局部变量数量和大小。

  • OutOfMemoryError : 增加内存。

参考

  1. https://docs.oracle.com/javase/7/docs/webnotes/tsg/TSG-VM/html/memleaks.html
  2. https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-2.html#jvms-2.5