1. jvm内存模型图解
jvm主要分为三大块,内装载子系统,运行时数据区,执行引擎,本文主要讲述运行时数据区的组成部分及各部分的作用
2. 运行时数据区(jvm内存模型)的组成
jvm内存模型讲的就是运行时数据区,运行时数据区由5部分组成,分别是堆(heap),栈(stack),元空间(Meta space1.7之前叫方法区),本地方法栈(Native Method Stack),程序计数器(Program Counter)
2.1 堆
堆内存存放java对象,比如我们new出来的对象一般会放在堆中,堆内存可以继续划分,下图中对堆内存继续分析
堆内存分为年轻代和老年代,新对象一般会放到年轻代的Eden区,
堆内存是线程共享的
堆内存在垃圾回收还会详细讲
2.2 栈
栈图解
线程栈,一种FIFO的数据结构,程序启动,会先开辟main线程的栈帧,在main方法中调用其他方法,会将新的栈帧压入栈。每个方法对应一块栈帧,当方法调用完之后,该方法对应的栈帧弹出栈。
在方法对应的栈帧中,分为四块,分别是局部变量表,操作数栈,动态链接,方法出口。局部变量表存当前方法对应的局部变量,操作数栈存储当前操作的数据。动态链接与静态链接区分,jvm在类加载的时候会把静态链接替换成对应的引用地址,动态链接就是在jvm运行的时候动态替换成引用地址。方法出口,就是该方法何时运行结束
栈内存是线程独有的
3. 元空间
jdk1.8代替了之前的方法区(永久代)
方法区存储着静态变量,常量池,以及类的元数据,方法区是线程共享的
在1.8移除了方法区,取而代之的是元空间,元空间本质上与方法区类似,最大的区别在于方法区本质上属于堆内存的一部分,为了与堆区别,称之为非堆,所使用的是虚拟机内存,这样的方法区会造成OOM(内存泄漏),元空间是与堆完全区别的概念,它使用的是本地内存(机器的物理内存),元空间理论上是可以无限大的(最大不能超过本地内存),因此基本不会造成内存泄露问题。我们可以通过
-XX:MetaspaceSize=xx和-XX:MetaMaxspaceSize=xx设置元空间的初始值和最大值,元空间是会发生full gc的,但是full gc回收的量会很少,如果不配置这两个参数name虚拟机默认初始值约21M,并且动态扩容和减少,-XX:MetaMaxspaceSize=-1,无穷大。
有时候启动程序很慢,就是因为元空间太小,每次满了之后出发full gc,触发的次数很多,所以程序启动会很慢,可以适当调大元空间初始值,一般对于8G的物理机来说,-XX:MetaspaceSize和-XX:MetaMaxspaceSize都设置为256M比较合适
4. 程序计数器
程序计数器受cup控制,记录下代码执行的行数,当线程继续执行的时候从记录的行数继续执行
5. 本地方法栈
存储着程序用到的native方法,native方法是物理机的本地方法,一般是由c/c++实现