1.Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域
程序计数器、虚拟机栈、本地方法栈、堆、方法区
2.程序计数器
①、线程私有
②、定义:程序计数器(Program Counter Register)是一块较小的内存空间,它可以看作是当前线程所执行的字节码的行号指示器。它是程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。
③、一个线程一个时刻只能执行一个指令,所以需要程序计数器来找到指令
3.虚拟机栈
①、线程私有,生命周期和线程相同
②、定义:虚拟机栈描述的是Java方法执行的线程内存模型:每个方法被执行的时候,Java虚拟机都会同步创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态连接、方法出口等信息。每一个方法被调用直至执行完毕的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。
“栈”通常就是指这里讲的虚拟机栈,或者更多的情况下只是指虚拟机栈中局部变量表部分。局部变量表存放了编译期可知的各种Java虚拟机基本数据类型(boolean、byte、char、short、int、float、long、double)、对象引用(reference类型,它并不等同于对象本身,可能是一个指向对象起始地址的引用指针,也可能是指向一个代表对象的句柄或者其他与此对象相关的位置)和returnAddress类型(指向了一条字节码指令的地址)。这些数据类型在局部变量表中的存储空间以局部变量槽(Slot)来表示,其中64位长度的long和double类型的数据会占用两个变量槽,其余的数据类型只占用一个。
③、在《Java虚拟机规范》中,对这个内存区域规定了两类异常状况:
- 如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常;
- 如果Java虚拟机栈容量可以动态扩展,当栈扩展时无法申请到足够的内存会抛出OutOfMemoryError异常。
4.本地方法栈
①、线程私有
②、定义:和虚拟机栈很像,虚拟机栈为虚拟机执行Java方法(也就是字节码)服务,而本地方法栈则是为虚拟机使用到的本地(Native)方法服务。
③、本地方法(Native):操作系统给我们暴露出来的方法
字节码:jvm可以理解的方法,即.class文件。他不面向任何特定的处理器,只面向java虚拟机
5.堆
①、线程公有
②、定义:类有哪些属性、静态变量等的蓝图存在方法区中,new对象的时候复制一份到堆
6.方法区
①、线程公有
②、方法区(Method Area)与Java堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据。
7.运行时常量池(方法区的一部分)
①、线程公有
②、常量池存在的意义:常量池存在以前有多少个String对象就创建多少String,有常量池可以节省空间
③、String a = "aa"不需要在堆里创建对象,在常量池中创建aa
String b = new String("bb")需要先在堆里创建一个bb,然后指向常量池中的bb
④、b.intern():对于第c行中的b来说返回的是字符串在常量池中的地址
⑤、所有的字符串都肯定存在于字符串常量池中
8.直接内存(了解)
①、并不是虚拟机运行时数据区的一部分,JVM不仅可以管理他的区域,还可以管理他之外的区域
9.练习 (各内存区的应用)
①、(userName为1)基础数据类型存在栈帧中,a和b不在一个栈帧中
改为Integer仍为1,因为Integer自动拆装箱
②、(zc1),引用数据类型从始至终只new了一个对象
③、zc1,zc1