整合网上各种java内存划分
上篇文章写了”关于java运行时的内存情况“,也就是java的内存划分情况,但是上网查了很多文章,发现对于内存分配这块有很多的不同说法,现在整理汇总一下:
本人原先认为内存分配情况:程序计数器、虚拟机栈、本地方法栈、堆区、方法区,还有一个直接内存
网上被广泛认可的一种说法:
◆寄存器:我们在程序中无法控制
◆栈:存放基本类型的数据和对象的引用,但对象本身不存放在栈中,而是存放在堆中
◆堆:存放用new产生的数据
◆静态域:存放在对象中用static定义的静态成员
◆常量池:存放常量
◆非RAM存储:硬盘等永久存储空间
代码段:用来存放从硬盘上读取的源程序代码。 数据段:用来存放static定义的静态成员。还有很多说法,就不一一说明了,内存的功能就那么多,很多只是叫法不一样,功能是一样的。
比较上面不同的分配
1、程序计数器 - 寄存器
上篇文章说程序计数器用于指示当前线程所执行的字节码执行到了第几行,只是寄存器的一种,jvm寄存器还有其他几种常用的pc程序计数器、optop操作数栈顶指针、frame当前执行环境指针、vars指向当前执行环境中第一个局部变量的指针。所以程序计数器只是寄存器的一种,不过寄存器是我们程序不可控制的,所以我们也不追究那么多了。
2、直接内存 - 非RAM存储
都是说的是机器整个内存中除了jvm内存外的内存
3、虚拟机栈、本地方法栈 - 栈
前面所说的JVM栈和本地栈合起来就是一个栈
4、堆区、方法区 - 堆、静态域、常量池
这几个有点混乱,前面我也说了堆区跟方法区是单独的,而查了很多资料发现主流观点是静态域存放在方法区,JDK8之前,静态成员变量确实存放在方法区;但JDK8之后就取消了“永久代”,取而代之的是“元空间”,永久代中的数据也进行了迁移,静态成员变量迁移到了堆中(方法区是JVM的规范,永久代是方法区的具体实现)。
再说常量池,有些文章认为常量池在堆中,但是翻阅资料发现这种观点是不完整的,Java7之前,常量池是存放在方法区的,但是在jdk1.7时,常量池被移动到了堆区,同时在jdk1.8中移除整个永久代,取而代之的是一个叫元空间(Metaspace)的区域。