1.程序计数器--线程私有,生命周期与线程一致(执行java方法时,则是虚拟机字节码指令的地址,定长。若是native方法,则为空,所以这个内存不存在outOfMemeryError,也没有规定)
每个线程都会拥有(因为多线程执行,上下文切换,需要保留当前线程执行状态),,记录当前线程执行的代码(字节码)行号,(字节码解释器工作试就是通过改变这个行号,来取下一条指令)
2.虚拟机栈(jvm粗分堆 栈 ,堆是统称,栈就是虚拟机栈)
线程私有,生命周期与程序计数器一样。每个方法执行的时候,都会在 虚拟机栈上创建于个栈帧,存放局部变量表,操作数栈、动态链接、方法出口等。
局部表量表存放的是:编译期可知的各种基本数据类型、对象引用);应该是所有基本数据类型 和 Java类(指针)的"描述信息",特指需要的内存大小?当程序计数器直到一个方法调用时,就会动态分配一个栈帧,这个栈帧所需要的内存大小,会根据方法内涉及到的 基本类型、类型指向动态计算大小。当程序编译时,,小恒徐内的 所有基本数据类型 和 Java类(指针)的"描述信息" 都已经确认了,,存放这些信息的 局部表量表 大小程序编译期就固定了。(所以定义了对应的over异常)。当线程请求的栈帧深度 超过 虚拟机栈 承受范围,,就抛*Error。但是有的版本jvm, 虚拟机栈 可动态扩展,,若达到扩展的限定后,则抛的是OutOfMemoryError。
操作数栈:存放的是需要计算的变量,类似于cpu寄存器?为运算器服务?https://blog.csdn.net/myle69/article/details/80379137
动态链接,,https://blog.csdn.net/championhengyi/article/details/78760590
方法出口:一块内存,,存放 直接或间接指向 返回 对象的存储地址描述信息。程序计数器 跳出方法后,,会将指向方法的返回的句柄,指向 该方法的 方法出口?(个人认为)。
3.本地方法栈 和 虚拟机栈一样 只不过 这个是 native方法(C C++)执行时用的,有的jvm直接放一起,
4.堆(地址不一定是连续的,,也会是不连续的,-Xmx -Xms控制)
这块是所有线程共享的内存,随着虚拟机的启动创建 ,就是存放java类对象。
gc管理的重点对象,为了更好的管理,回收,,在这上面再划分 新生代、老年代、永久带等,甚至有更细的划分,,一个对象在 新生代 上创建,然后被GC,生存一段时间后,,复制到老年代,,在老年代 GC的频率低一点,,再不”死“就到永久带,GC频率更低,,因为GC也是有消耗的啊。
https://www.cnblogs.com/likehua/p/3369823.html
5.方法区,这块是所有线程共享的内存,编译器加载的类信息、常量、静态变量等。(就是存放所有类的描述信息,,class类?)
https://blog.csdn.net/SunshineLPL/article/details/78318709?locationNum=9&fps=1
重点了解下,运行时常量池,字段,方法信息,静态变量,类型引用(class)
6.直接内存
NIO引入的基于Channel Buffer 的IO方式,调用native方法直接分配堆外内存,,
所以对象访问,就是 句柄在栈帧中 实例在堆中 类对象信息在方法信息