java虚拟机在执行java程序的过程中会把它管理的内存划分为若干个不同的数据区域。
1. 程序计数器
程序计数器是一块比较小的区域,它可以看作为当前线程所执行的字节码的行号指示
器。字节码解析器工作时就是通过改变程序计数器的来选取下一条需要执行的字节码
指令,分支、循环、跳转、异常处理、线程恢复等基础功能都要依赖程序计数器去完
成。
由于java虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的,
因此为了线程切换后能恢复到正确的执行位置,因此每个线程都需要一个独立的程序
计数器。
如果线程执行的是一个java方法,那么这个计数器记录的是正在执行的虚拟机字节码
指令地址;如果执行的是一个native方法,那么这计数器的值为空。此区域是唯一一
个java虚拟机规范中没有规定任何OutOfMemoryError请求的区域。
为什么需要程序计数器?
因为java是多线程的,为了避免进程切换的时候程序不能正常执行。
2.java虚拟机栈
与程序计数器一样,java虚拟机栈也是线程私有的,它的生命周期与线程相同。每个
java方法在执行的时候都会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、
方法出口等下信息。每一个方法从调用直到方法执行完成的过程,就对应一个栈帧在虚
拟机中入栈到出栈的过程。
java虚拟机规范中对这个区域规定了两种异常:如果请求的栈深度大于虚拟机最大允
许的栈深度,将抛出StackOverflowError异常;如果虚拟机栈可以动态拓展,如果拓
展时无法申请到足够的内存,则将抛出OutOfMemoryError
3. 本地方法栈
本地方法栈所发挥的作用跟虚拟机栈是非常相似的,他们的区别是虚拟机栈是为虚拟机
执行java方法服务,本地方法栈则是为虚拟机执行native方法服务的。
4. java堆
java堆是虚拟机所管理的内存的最大的一块。java堆是被所有线程共享的一块区域,在虚
拟机启动时创建。此区域唯一目的是存放对象实例,几乎所有对象实例都在这里分配内存。
java堆是垃圾回收的主要区域。
5.方法区
方法区跟java堆一样,是各个线程共享的区域,它用作于存储已被虚拟机加载的类信息、
常量、静态变量、即时编译器编译后的代码数据等。
当方法去无法满足内存分配需求时,将抛出OutOfMemoryError异常。
6. 运行时常量池
运行时常量池是方法区的一部分。Class文件除了有类的版本、字段、方法、接口等描述
信息以外,还有一项信息是常量池,用户存放编译期生成的各种字面量和符号引用,这些
信息会在类加载完成后存放在方法区中的运行时常量池。
既然是方法区的一部分,自然受到方法区的内存限制,当无法申请到内存时会抛出
OutOfMemoryError异常。
7. 直接内存
直接内存并不是虚拟机运行时数据区的一部分,也不是java虚拟机规范中定义的内存
区域。直接内存的内存分配不会受到java堆的大小限制。会受到本机总内存的限制。
总结一下:
线程私有的区域有:程序计数器、java虚拟机栈、本地方法栈
线程共享的区域有:java堆、方法区
JVM-内存区域划分
最新推荐文章于 2024-08-03 10:06:40 发布