运行时数据区域:
(1)、程序计数器
a、定义:是一块较小的内存空间,可以看作是当前线程所执行的字节码的行号指示器。
b、线程私有:因为多线程是通过线程轮流切换并且分配处理器执行时间的方式来实现的,任何时刻,
一个处理器都只会执行一条线程中的指令。线程切换后要恢复到正确的执行位置,所以每条线程
都有一个独立的程序计数器。互不影响,独立存储。
c、线程执行java方法,计数器才会记录字节码的地址,native方法计数器值是undefined。
d、内存区域是唯一一个在java虚拟机中是没有任何OutOfMemoryError情况的区域。
(2)、java虚拟机栈
a、线程私有,生命周期与线程相同。
b、java虚拟机栈描述的是java方法执行的动态内存模型。
c、方法执行中创建一个栈帧:存储局部变量表,操作数栈,动态链接,方法出口灯信息。
一个方法的执行完成,其实就是java虚拟机中一个栈帧在java虚拟机中的入栈到出栈过程。
d、栈深度大于虚拟机最大深度抛StackOverflowError.
e、栈无限制动态扩展,eg:方法中死循环,会抛OutOfMemoryError。
(3)、本地方法栈
a、本地方法栈描述的是native方法执行的动态内存模型。
b、没有语言数据结构强制规定,甚至sun hotspot虚拟机把本地方法栈和java虚拟机栈合二为一。
c、会抛出StackOverflowError,OutOfMemoryError。
(4)、Java堆(Java Heap)
a、java堆是所有线程共享的一块区域,虚拟机启动时候创建。
b、用处:存放对象实例。几乎所有的对象实例都是在这里分配内存。(不是所有)
c、也是垃圾收集器的主要区域,也被称为“GC堆”。
(5)、方法区(Method Area)
a、方法区与堆一样,是各个线程共享的内存区域,它用来存储已经虚拟机加载的类信息,常量,静态变量,
即时编译器编译的代码等数据。别名:Non-Heap(非堆)。
class文件的信息(类的信息):类版本,字段,方法,接口。
b、方法区和永久带并不是恒等,不同类型的虚拟机规范不一样;
c、垃圾回收再方法区很少出现,主要是针对常量池的回收和对类型的卸载。回收效率不是很高。
d、方法区无法满足内存分配需求时,将抛出OutOfMemoryError异常。
(6)、运行时常量池(Runtime Constant Pool)
a、RCP是方法区的一部分。
b、class文件(还有一个信息)的常量池(Constant Pool Table)存放编译器生成的各种字面量和符
号引用,这部分内容将在类加载后进入方法区的运行时常量池中存放。
c、运行时常量池相对于Class文件常量池具备动态性。
运行期间也可能将新的常量放入运行时常量池中,并非预置入Class文件中的常量池才能进入RCP。
eg:String 类中的intern()方法。
d、java虚拟机规范对Class文件每一部分有严格的规定,而对运行时常量池,没有作严格细节要求。
(7)、直接内存
a、直接内存并不是虚拟机运行时数据区的一部分,也不是Java 虚拟机规范中农定义的内存区域。
b、在JDK1.4 中新加入了NIO(New Input/Output)类,引入了一种基于通道(Channel)与缓冲区(Buffer)的I/O 方式,
它可以使用native函数库直接分配堆外内存,然后通脱一个存储在Java堆中的DirectByteBuffer 对象作为这块内存
的引用进行操作。这样能在一些场景中显著提高性能,因为避免了在Java堆和Native堆中来回复制数据。本机直接内
存的分配不会受到 Java 堆大小的限制,受到本机总内存大小限制配置虚拟机参数时,不要忽略直接内存 防止出现
OutOfMemoryError异常。
c、byte byffer可以是两种类型,一种是基于直接内存(也就是非堆内存);另一种是非直接内存(也就是堆内存)。
对于直接内存来说,JVM将会在IO操作上具有更高的性能,因为它直接作用于本地系统的IO操作。而非直接内存,
也就是堆内存中的数据,如果要作IO操作,会先复制到直接内存,再利用本地IO处理。
d、从数据流的角度,非直接内存是下面这样的作用链:
本地IO-->直接内存-->非直接内存-->直接内存-->本地IO
而直接内存是: 本地IO-->直接内存-->本地IO
二、Java虚拟机自动内存管理机制、运行时数据区域深入了解
最新推荐文章于 2023-07-19 23:44:25 发布