JVM-02-JVM内存模型

117 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第1天,点击查看活动详情

JVM内存模型

整个Java程序作为一个大进程,内部被分成了不同的部分,同时也分成了很多不同的线程,不同的线程间既有私有的部分,也有共享的部分。

线程私有的部分

线程私有分为三个部分,分别为线程栈,程序计数器和本地方法栈。线程根据程序计数器读取指令,实现代码流程控制,本地方法栈则是为Native方法服务。而线程栈比较复杂,将进一步分解。

线程栈

线程栈中包括许多个栈帧,每一个栈帧代表着线程不同的方法。其中每一个栈帧主要分为四个部分,分别是局部变量表,操作数栈,动态链接以及方法出口。

在程序运行时,会将数据通过iconst操作将数据压入操作数栈中,再通过istore操作出栈并保存到局部变量表中。如果需要从局部变量表中取值,将通过iload操作把局部变量表中的值压进操作数栈中,最后通过如iadd,imul等操作去对操作数栈中的数据进行计算。最后再通过istore保存回局部变量表中。

在JVM参数设置中,可以通过 -Xss 去设置栈的大小。

线程公有的部分

线程公有分为两个部分,分别为堆,方法区。

在堆中通常分为新生代和老年代,其中新生代默认根据8:1:1的比例分为Eden区,S0和S1(也可以通过 -XX:UseAdaptiveSizePolicy 去设定自适应大小),发生在新生代中的垃圾回收被称为Young GC或者Minor GC。整体的新生代空间可通过参数 -Xmn 进行调整。

老年代没有分区,但是老年代在整个堆中的大小是默认是大于新生代的,默认的比例为1:2(可通过 -XX:newRadio 进行设置),如果老年代空间不足将会发生Full GC。

通过 -Xms 去设置堆的初始值,以及 -Xmx 设置堆的最大值。

方法区

方法区用于存储类的运行时数据结构,比如类型信息,常量,静态变量等。

可通过 -MaxMetaspaceSize 参数设置方法区的最大值,通过 -MetaspaceSize 设置方法区的初始值。

总结

以上就是JVM基本的内存模型,一个对象从类加载,到对象空间内存分配,再到最后被垃圾回收都发生在上述的内存空间中,下一部分将把前两部分的内容串起来,讲一下一个对象到底是怎么产生的,感谢观看。