java-虚拟机-内存溢出

内存划分

1. 运行时数据区

- 堆 可能划分出多个线程私有的分配缓冲区tlab 在使用完tlab时会分配新的tlab这期间申请内存会同步锁定

- 虚拟机栈

- 本地方法栈 会抛出stackOverFlowError/OutOfMemoryError

- 方法区  存储虚拟机加载的类信息/常量/静态常量/及时编译后的代码

  运行时常量池 是方法区的一部分,存放编译期生成的字面量/符号引用 并非编译期/预置入class文件中常量池的内容才能进入 运行期间调用intern()方法也会 会抛出OutOfmemoryError

- 程序计数器(唯一一个没有outOfMemoryError的区域)

2. 非运行时数据区

- 直接内存

 

对象的创建

 

1. 遇见new指令 根据指令的参数首先去常量池中定位到一个类符号引用 检查符号引用代表的类是否被加载 解析 初始化过

2. 类加载检查通过后 分配内存  

3. 初始化0值

4. 显示初始化

 

内存区域溢出

堆溢出

通过参数-XX:+HeapDumpOnOutOfMemoryError 内存溢出时dump出当时的内存快照

栈溢出/本地方法栈溢出

1.当栈深度大于虚拟机运行的栈深度会抛出StackOverFlowError

2. 在扩展时无法申请到足够的内存空间抛出OutOfMemoryError

当单线程时只会抛出StackOverFlowError

多线程时会抛出OutOfMemoryError  操作系统给进程分配的内存大小是固定的,jvm通过xmx控制最大堆容量 MaxPermSize控制最大方法区容量 程序计数器太小可以忽略 剩下的就由虚拟机栈和本地方法栈瓜分

如果是过多的线程导致内存溢出,在不能减少线程数和更换内存的情况下,只能减少堆或减少栈容量来换取更多的线程 

方法区

1. 方法区中存储class的相关信息,导致溢出的情况是运行时产生大量的类

使用cglib创建过多代理类会导致方法区溢出

大量jsp文件或者动态产生jsp文件的应用(jsp在第一次运行时需要编译成java文件)

直接内存

可以通过-XX:MaxDirectMemorySize指定默认使用java堆最大值

posted @ 2022-05-06 21:45  rudynan  阅读(25)  评论(0编辑  收藏  举报