研究了一波JVM,自己把手头的资料做一些整理。
图出处:https://www.cnblogs.com/xiaofuge/p/14244755.html
图中大概可以看出一个梗概,那就是方法区(永久代)的逐渐消亡,从主内存中逐渐变到本地内存中。
Hotspot中 方法区的变化:
原来方法区存储了类的元数据信息和各种常量,而且他也受GC的管理,而GC的目标理应当是对这些类型的卸载和常量的回收。但由于这些数据被类的实例引用,卸载条件变得复杂且严格,回收不当会导致堆中的类实例失去元数据信息和常量信息。因此,回收方法区内存不是一件简单高效的事情,往往GC在做无用功。另外随着应用规模的变大,各种框架的引入,尤其是使用了反射,动态代理等字节码生成技术的框架,对于方法区的大小设置无法把控,会导致方法区内存占用越来越大,最终OOM,那把方法区剔除出来是当务之急。
JVM内存模型可以分为两个部分,堆和方法区(元空间)是所有线程共有的,而虚拟机栈,本地方法栈和程序计数器则是线程私有的。为了形象说明,参见下图:
图出处:https://www.cnblogs.com/yanl55555/p/13323128.html
与虚拟机栈基本类似,区别在于虚拟机栈为虚拟机执行的java方法服务,而本地方法栈则是为Native方法服务,普通开发可以忽略。JDK1.8 HotSpot虚拟机直接就把本地方法栈和虚拟机栈合二为一。
java方法执行的内存模型——栈帧:用于存储局部变量表(包括参数)、操作栈、方法出口等信息。每个方法被调用到执行完的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。生命周期与线程相同,无线程安全的顾虑,因为都是线程单独私有的。
-Xss设置每个线程堆栈的大小。一般情况下256K是足够了。
存放方法参数和方法内部定义的局部变量(包括对象引用)。注意如果是成员变量,或者定义在方法外对象的引用,它们存储在堆中,涉及到线程共有的都在堆中,如果都是私有,也就没线程安全这一说了。
局部变量表的容量以变量槽slot为最小单位,每个变量槽都可以存储32位长度的内存空间,例如boolean、byte、char、short、int、float、reference。其中64位长度的long和double类型的数据会占用2个空间,同时slot支持复用。
局部变量表所需的内存空间在编译期间完成分配,当进入一个方法时,这个方法需要在栈帧中分配多大的局部变量是完全确定的,在运行期间栈帧不会改变局部变量表的大小空间。
原文:https://www.cnblogs.com/zhou-yuan/p/14252272.html