深入jvm第二版——第二部分_2.1java内存区域与内存溢出异常
第2章 java内存区域与内存溢出异常
2.2 运行时数据区域
-
程序计数器:内存空间较小,可以看做当前线程所执行的字节码的行号指示器。
字节码解释器工作时就是改变这个计数器的值来选取下一条所需要执行的字节码指令。
因为多线程是通过线程轮流切换并且分配处理器执行时间的方式实现的,所有每条线程都需要一个独立的程序计数器。这类内存区域成为“线程私有”的内存。 -
java虚拟机栈:也是线程私有的,生命周期和线程相同。
虚拟机栈描述的是Java方法执行的内存模型:每个方法在执行的同时都会创建一个栈帧用于储存局部变量表、操作数栈、动态连接、方法出口等信息。方法从调用到执行完成,对应着一个栈帧在虚拟机栈中入栈和出栈。局部变量表存放了编译器可知的各种基本数据类型(boolean、byte、char、short、int、float、long、double)、对象引用(reference类型,不等同于对象本身,可能是一个指向对象起始地址的指针,也可能是指向一个代表对象的句柄或其他与此对象相关的位置)和returnAddress类型(指向了一条字节码指令地址)。
局部变量表所需内存空间在编译期间完成分配。当进入一个方法时,这方法需要在帧中分配多大的局部变量空间是完全确定的,不会改变。 StackOverFlowError异常、OutOfMemoryError异常 -
本地方法栈: 与虚拟机栈作用相似。
区别:虚拟机执行java(字节码)服务,而本地方法栈为虚拟机使用到的Native方法服务。StackOverFlowError异常、OutOfMemoryError异常 -
Java堆: 大部分应用指java虚拟机管理的内存中最大的一块。被所有线程共享,在虚拟机启动时创建。
目的:存放对象实例,几乎所有对象实例在这里分配内存。
是垃圾收集器管理的主要区域,也叫做**“GC堆”**Garbage Collected Heap。第3章学。Java堆可以处于物理上不连续的内存空间,只要逻辑是连续即可。
-
方法区:各个线程共享的区域,用于储存已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。别名:“Non-Heap非堆”,与java堆区分开来。
限制非常宽松,除了跟java堆一样不需要连续的内存和可以选择固定大小和可扩展外,还可以选择不实现垃圾收集。
当方法区无法满足分配内存需求时,OutOfMemoryError -
运行时常量池:方法区的一部分。存放Class文件的常量池(存放编译期生成的各种字面量和符号引用)。
一般来说,除了Class文件中描述的符号引用外,还会把翻译出来的直接引用也储存在运行常量池中。
另一个特征:具备动态性,java语言并不要求常量一定只有编译期才能产生,也就是并非预置入Class文件中常量池的内容才能进入方法区运行常量池,运行期间也可能将新的常量放入池中。如String类的intern()方法。 -
直接内存:不是虚拟机运行时数据区一部分,也不是java虚拟机规定中定义的内存区域。
HotSpot虚拟机对象探秘
### 对象创建(看书)
new指令,首先检查参数能否在常量池中定位到一个类的符号引用,
并且检查这个符号引用代表的类是否被加载、解析和初始化过。
如果没有就必须先执行相应的**类加载**过程,第7章学。