1、运行时数据区域
Java虚拟机在执行Java程序的过程中会把它管理的内存分为若干个不同的数据区域。这些区域有着各自的用途,一级创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有些区域则依赖用户线程的启动和结束而建立和销毁。根据《Java虚拟机规范》中规定,jvm所管理的内存大致包括以下几个运行时数据区域,如图所示:
image.png
2、程序计数器
程序计数器是线程私有的,它是当前线程所执行的字节码的行号指示器,更直白的说就是执行到哪一行代码了。为什么要有程序计数器呢?因为在多线程下,线程是交替执行的,这是由操作系统决定的。所以需要程序计数器来记录线程字节码执行到哪一行了,下次线程切换回来才能从上次执行的地方继续执行。
- 如果线程执行的是Java方法,则程序计数器记录的是当前线程的虚拟机字节码的地址。(执行到哪一行)
- 如果执行的是native方法,程序计数器值为空
3、Java虚拟机栈
这虚拟机栈就是平时我们说的堆栈中的栈,也是线程私有的。
虚拟机栈描述的是Java方法执行的内存模型,每个方法在执行的同时都会创建一个栈帧 用于存储局部变量表,操作数栈,动态链接,方法出口等信息。每一个方法从调用直至完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。
4、本地方法栈
本地方法栈和虚拟机栈的作用非常相似。不同的是虚拟机栈为Java方法(字节码)服务。本地方法栈为native方法服务,虚拟机规范中堆native方法使用什么语言,数据结构没有规定,但一般是c,c++。
5、Java堆
堆是jvm管理的内存中最大的一块,是所有线程共享的一块区域。
堆的唯一目的就是存放对象实例的。几乎所有对象实例都存储在堆中。(不是全部哦)JIT编译器的发展与逃逸分析技术主键成熟,栈上分配,标量替换优化技术都会是对象实例内存分配发生微妙变化。所以不是所有对象实例都存放在堆中的 。
堆是垃圾收集器管理的主要区域 。
堆可以处于物理上不连续的内存空间中,但是逻辑上要连续。
6、方法区
和堆一样所有线程共享,主要用于存储已被jvm加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。(在JDK1.7发布的HotSpot中,已经把字符串常量池移除方法区了。)
7、运行时常量池
运行时常量池是方法区的一部分。Class文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池,用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后进入方法区的运行时常量池中存放。
Java虚拟机对class文件每一部分的格式都有严格规定,每一个字节用于存储哪种数据都必须符合规范才会被jvm认可。但对于运行时常量池,Java虚拟机规范没做任何细节要求。
运行时常量池有个重要特性是动态性,Java语言不要求常量一定只在编译期才能产生,也就是并非预置入class文件中常量池的内容才能进入方法区的运行时常量池,运行期间也有可能将新的常量放入池中,这种特性使用最多的是String类的intern()方法。
网友评论