这里说一下JVM的内存分成哪几部分,分别是干什么的。
总览如图所示,图片来自于书籍
——深入理解Java虚拟机:JVM高级特性与最佳实践(第3版) 周志明
这里线程隔离的数据区 意思是 每个线程都有自己的一份。
接下来呢,我们把目光放在运行时数据区,其他不管。
运行时数据区 程序计数器这个比较简单,就是标记程序执行到了哪一行,接下来应该执行哪一行。
这个在单线程的时候可能还意义不大,但是在多线程并发执行时,他的作用就很重要了。当一个线程执行到某条指令,需要切换其他线程执行,当前线程需要暂停。为了在切回该线程时,能够按照正确的顺序执行程序,需要标记行号。
Java虚拟机栈是每个线程自己独有的。
每个方法被执行的时候,Java虚拟机都会同步创建一个栈帧。如果不了解栈帧,虽然不准确,可以暂时理解为栈中的一个元素。栈帧中存储的是:局部变量表、操作数栈、动态连接、方法出口等信息。方法调用,栈帧被创建,入栈。方法执行完毕,出栈。
也就是说,虚拟机栈是与方法相关的。
局部变量表是虚拟机栈,栈帧内的一部分,比较重要,拿出来说说。
局部变量表中存放了 8大基本数据类型、reference类型 和 returnAddress类型。
reference类型 是 对象引用
returnAddress类型:
对于 JVM 来说,程序就是存储在方法区的字节码指令,而 returnAddress 类型的值就是指向特定指令内存地址的指针。
以上 10 种数据类型都是编译期就可以知道的。
本地方法栈与虚拟机栈类似。区别是 虚拟机栈 为 虚拟机执行Java方法服务,本地方法栈为虚拟机是用到的本地方法服务。
Java堆被所有线程所共享。
用于存放对象实例。几乎所有的对象实例都存储在这里。
举个例子:
Student Tom = new Student(); //Student是自定义的类
Tom 是 reference类型,存储在栈中。
new Student() 是对象实例,存储在堆中。
从分配内存的角度看,所有线程共享的Java堆中,可以划分出多个线程私有的分配缓冲区,用来提升对象分配时的效率。将Java堆细分的目的是为了更好地回收内存,或者更快地分配内存。
方法区用于存储已被虚拟机加载的 类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据。《Java虚拟机规范》中把 方法区 描述为堆的一个逻辑部分,但是它却有一个别名叫作“非堆”目的是与Java堆区分开来。
关于方法区,有点说道的,这里不多介绍,详见:
这有个博客链接,还没写,明早写。
好啦,这一篇就到这里了。
早睡早起,注意身体。早起之王,祝你风生水起。



