JVM内存空间
1. 方法区
方法区:用于存放JAVA中的对象类具体信息(类的版本、字段、方法、接口等等描述信息)、静态变量、常量等信息。
方法区无法满足内存需求的时候抛除OutOfMemory异常
方法区因为需要存储常量,所以需要创建一个运行时常量池。
运行时常量池用于存放编译器器件生成的各种字面量以及引用。
2.堆
堆:用于存放JAVA中的基本所有对象实例。JAVA的堆容量是可以设置的,-Xms 用于设置开始的内存,当虚拟机检测到堆的内存不足以存储对象的时候,会自动拓展堆的容量,-Xmx用于设置可以拓展的最大内存,如果堆无法拓展,那么会爆出OutOfMemory的异常。
public class HeapOOM {
static class OOMObject{
}
public static void main(String args[]){
List<OOMObject> list = new ArrayList<OOMObject>();
while(true) {
list.add(new OOMObject());
}
}
}
console区会爆出异常的具体信息:
Exception in thread “main” java.lang.OutOfMemoryError: Java heap space
3.JAVA虚拟机栈
为每个方法都会创建一块区域用于存储局部变量表、方法出口、操作数栈。
因此合理的,JAVA虚拟机栈一定是线程私有的。
当线程创建的栈超过了虚拟机允许的深度,会抛出StackOverflowError的异常,
当虚拟机申请不到足够的内存时,就抛出OutOfMemory的异常。
4.本地方法栈
因为JAVA底层有一些东西是跟系统交互的,需要使用到系统底层的方法,所以当JAVA调用这部分方法的时候,需要建立一个栈用于存储调用系统方的相关内容。
JAVA虚拟机栈中会为每一个方法执行创建局部变量表,用于存储:各种基本数据类型(char,int,double,float,long,byte,boolean)以及reference类型(用于指向具体的对象实例或者用于指向该对象的句柄)。
5.程序计数器
计算机通过计数器来指向现在应该执行的指令,执行完该指令之后,程序计数器会实时更新,因此程序计数器并不需要很大的空间,同时合理的,每一个线程都会自建一个自己的程序计数器。
直接内存
自从JDK1.4之后出现了新的类NIO,可以使用native函数直接分配堆外的内存,然后使用Java堆中的DirectByteBuffer对象作为这块内存的引用来使用,因此其大小并不影响堆的大小。
方法区跟堆都是所有线程都可以访问的内存区域。
线程私有的内存区域有:程序计数器、JAVA虚拟机栈、本地方法栈。