Java内存区域
Java虚拟机运行时它所管理的区域分成若干个不同的数据区域。主要包括两部分,一部分是线程隔离的,也就是说每个线程独自拥有的内存区域,另一部分是线程共享的,每个线程都能对其进行访问。线程隔离的部分又分为三个模块,分别是程序计数器、虚拟机栈和本地方法区。线程共享部分分为两个模块,堆和方法区。
- 程序计数器
程序计数器中主要记录当前线程所执行的字节码的行号地址。
若为Java方法,则为当前的字节码地址;若为本地方法,则为null。
程序计数器不会抛出任何异常。
- 虚拟机栈
虚拟机栈中主要包括局部变量表、操作数、动态链接和方法出口等。每一个方法有一个桢栈,线程对方法的调用和完成相当于在虚拟机栈中对桢栈的入栈和出栈。其中局部变量表中主要记录各种局部变量、方法参数、returnAddress(指向下一条指令的地址)和引用。操作数主要记录方法的操作数,便于存入和提取数据。动态链接中包含一个指向运行时常量池中该桢栈方法的引用,便于对方法的动态链接。方法出口中主要包含方法的返回地址,当正常退出时,用程序计数器作为返回地址;当异常退出时,用异常变量表来确定。
虚拟机栈可能会抛出StackOverflowError(当请求的栈深度高于虚拟机栈深度)和OutOfMemoryError(当无法再为其分配内存),可采用-Xss来设置虚拟机栈容量。
- 本地方法区
用来处理那些本地方法,即非Java方法。
也会抛出StackOverflowError和OutOfMemoryError异常
- 堆
在堆中主要存储new出来的对象和数组,也称为GC堆。
主要分为新生代和老年代
新生代又分为Eden区和两个Survivor区(from和to),主要存储生命周期比较短,比较活跃的对象
老年代主要存储一些大的对象,不活跃的对象,以及一部分从新生代晋升来的对象。
可能会抛出OutOfMemoryError异常
可采用-Xmx(最大值)、-Xms(默认值)以及-Xmn(新生代大小)来设置堆大小
- 方法区
主要存储虚拟机加载的类文件、静态变量和常量、即时编译后产生的代码等。可不需要垃圾回收、连续内存
会抛出OutOfMemoryError
可使用-XX:PermSize和-XX:MaxPermSize设置方法区大小
- 运行时常量池
方法区的一部分,存放编译器生成的各种字面量和符号引用。具备动态性,运行期间可以有新的常量加入。如String.intern()函数。
- 直接内存
直接内存非JVM一部分,但也有可能抛出OutOfMemoryError.
NIO的DirectByteBuffer实现对这块内存的操作,可使用-XX:MaxDirecttmemorySize设置直接内存大小,默认与堆大小相同