JVM内存的五个区域
线程私有区:
1. 程序计数器:
-
当前线程所执行的字节码的行号指示器(字节码解释器工作时就是改变这个计数器的值来选取下一条执行的字节码指令)
-
Java虚拟机的多线程是通过线程轮流切换、分配处理器执行方式实现的(即:在任何一个确定的时间,一个处理器都只能执行一条线程中的指令)因此,为了线程切换后能恢复到正确的执行位置,线程私有,(即:每条线程都有一个独立的程序计数器)
-
执行Java方法-------计数器记录的是正在执行的虚拟机字节码指令的地址
-
执行本地(Native)方法-------计数器的值为空
-
注:唯一一个在《Java虚拟机规范》内存区域没有规定任何OutOfMemoryError情况的区域
2. Java栈(虚拟机栈)
-
生命周期与线程相同
-
Java方法执行的内存模型
-
每个方法被执行时,栈中同步创建一个帧栈用来存储局部变量表、操作数栈、动态连接、方法出口等
-
方法被调用------入栈;方法执行完毕------出栈
-
局部变量表存放一些基本类型的变量(int,short,long,byte,float,double,boolean,char)、对象引用和returnAddress类型
-
对象引用:reference类型,并不等同于对象本身,可能是指向对象起始地址的引用指针,也可能是指向代表一个对象的句柄或其他与此对象相关的位置
-
returnAddress:指向了一条字节码指令的地址
-
拓展:
-
这些数据类型在表中的存储空间以局部变量槽(Slot)表示,其中64位的long和double会占2个变量槽(其余一个)
-
局部变量表所需内存在编译期间完成分配,
-
-
-
如果线程请求的栈深度>虚拟机的所允许深度时throw StackOverflowError
-
如果java虚拟机栈容量可以动态扩展,当栈扩展时无法申请足够内存时会throw OutOfMemoryError
3. 本地方法栈(Native Method Stacks)
-
与虚拟机栈类似,区别在于虚拟机栈为虚拟机执行Java方法(字节码)服务,本地方法栈为虚拟机使用到的本地方法服务
-
扩展:
-
《Java虚拟机规范》没有对本地方法栈使用的语言、方式与数据结构没有强制规定,所以可以自由实现。
-
例如Hot-Spot直接就把本地方法栈和虚拟机栈合二为一
-
-
也存在StackOverflowError和OutOfMemoryError
线程公有区
1. Java堆(Java Heap)
-
虚拟机所管理的内存最大的一块
-
被线程共享,在虚拟机启动时创建
-
唯一目的:存放对象实例
-
Java堆时垃圾收集器管理的内存区,所以也被称为“GC堆”
-
可以划分出多个线程私有的分配缓冲区,以提升对象分配时的效率
2.方法区(Method Area)
-
存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码
-
和Java堆一样不需要连续的内存
-
存在OutOfMemoryError
-
运行常量池是方法区的一部分
-
运行常量池具备动态性,并非预置入Class文件中的常量池的内容才会进入方法区运行时常量池,运行期间也可以将新的常量放入池中,例如:String类的intern()方法
-