JVM学习笔记一:Java运行时数据区域
1. 程序计数器
当前线程所执行的字节码的行号指示器。
2. Java虚拟机栈
线程私有,与线程具有相同生命周期。用于存储局部变量表、操作数栈、动态链表、方法出口等信息。
局部变量表存放内容:
- 基本数据类型(boolean、byte、char、short、int、float、long、double)
- 对象引用(区别于符号引用,符号引用存放在常量池)
- returnAddress类型(指向一条字节码指令的地址)
64位长度的long和double类型数据占用2个局部变量空间(slot),其余占用1个slot。
两种异常:
- StackOverflowError:线程请求的栈深度>虚拟机允许的深度
- OutOfMemoryError: 动态扩展时无法申请到足够内存
3. 本地方法栈(Native Method Stack)
与虚拟机栈类似,区别是Native Method Stack服务于Native方法,而虚拟机栈服务于Java方法。
4. Java堆(Java Heap)
所有线程共享,存放对象实例、数组。
垃圾收集器管理的主要区域,也称“GC堆(Garbage Collected Heap)”
包含新生代(Eden空间、From Survivor空间、To Survivor空间)、老生代。
可划分出多个线程私有的分配缓冲区(Thread Local Allocation Buffer,TLAB)。
物理上可以不连续,逻辑上连续。
可扩展:-Xmx和-Xms控制。-Xmx最大堆内存大小,-Xms初始堆内存大小。
当堆中没有可用内存完成实例分配,并且也无法再扩展时——OutOfMemoryError
5. 方法区(别名Non-Heap)
也是所有线程共享,用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
也称“永久代(Permanent Generation)”,但本质上并不等价。
永久代有-XX:MaxPermSize的上限。
6. 运行时常量池(Runtime Constant Pool)
属于方法区的一部分。
7. 直接内存(Direct Memory)
JDK1.4新加入的NIO(New Input/Output)类,引入了一种基于通道(Channel)与缓冲区(Buffer)的I/O方式,它可使用Native函数库直接分配堆外内存。不受Java堆大小(-Xmx)限制,从而可能造成各个内存区域总和大于物理内存限制而造成动态扩展时出现OutOfMemoryError。
小结:
- 1、2、3三种内存区域是各个线程私有的
- 4、5是所有线程共有的
- 6是5的一部分
- 7不是虚拟机运行时数据区的一部分,属于虚拟机的内存区域外的其他物理内存
zni.feng@gmail.com