JVM内存结构主要有:
其中,方法区在物理上是存在于堆区中的持久代中,见下图。1)堆区(Heap)
2)方法区
3)JAVA栈区(Stack)
4)本地栈
5)PC寄存器
堆:
1)Eden区:新对象或者生命周期很短的对象存储在这个区域(通过新生代GC)。
2)Survivor区:由Eden区中存活下来的对象(通过新生代GC)。
3)Old区:经历Eden和Survivo区多次新生代GC后仍能存活下来的对象(Old区是major Gc来清理)。
导致ava.Lang.OutOfMemoryError: Java Heap Space异常:
●生成大量对象(通过while,并将其放入一个ArrayList,这样就不会被GC掉了):因为新对象会存在于Eden区中,一旦超过Eden区的最大值就会溢出。
方法区:
1)持久代:类有关信息(方法、名称、常量和静态变量)、常量池信息(字面量和符号引用)。
创建一个对象时,如果是第一次访问,则类加载通过定位并加载所对应的class文件并解析。其中解析后的内容被保存在
方法区中(类名、方法信息、常量、静态变量等)。
导致Java.Lang.OutOfMemoryError: PermGen Space异常:
●通过不同的类加载类加载同一个class文件(对应的class实例不同)会导致持久代溢出
●String.intern()导致常量池溢出
JAVA栈区:
1)每个方法执行时会创建栈帧用于存储局部变量表(JVM中的一种数据结构)、操作栈、动态链接和方法出口等。
2)局部变量表:
●基本数据类型
●对象引用
●returnAddress(指向一条字节码指令地址)
局部变量表在编译期间就需确定内存大小。
导致java栈StackOverflowError:
●线程请求栈深度大于虚拟机所允许的(通过定义大量本地的变量)
导致OutOfMemoryError:
●java栈动态扩展无法申请到足够多的内存(通过定义大量的线程)
可以看出,在JVM调栈大小的参数时,不能一味地增加栈大小。