JVM内存模型解析

jvm是为GC做铺垫。


JVM内存模型分为5个区域。

在java运行时,JVM虚拟机拿到自己能支配的内存后,将内存进行割分为5个区域:

  • 栈区:存储函数当前运行过程中的临时变量。
  • 堆区:主要存对象
  • 本地方法栈:存储c++等native运行时候的栈区
  • 程序计数器:指向程序当前运行的位置。
  • 方法区: 存储一些元数据信息。JDK7之前叫永久代。JDK8+改为元数据空间。主要存储一些静态的方法和变量、类加载器、全局的变量等。

栈区、本地方法栈、程序计数器3部分合起来:线程私有。

即每个线程在运行和开辟的过程中会单独的创建这样一份内存。有多少个线程,可能就会有多少个这3部分。

堆区、方法区是全局共享的。



栈区存储函数当前运行过程中的临时变量和堆区存储对象不矛盾:

栈区存储的对象实际存储的是对象的引用类型,即存储的是对象的地址。

最终是指向堆区中实际存储的对象的。


小例子理解函数运行过程中内存是如何调用的:

1.值类型:

以fun()为例,首先在运行过程中它拿到了一个参数a,此时:

然后又定义了一个临时变量b,并打印了a+b,且最后给a赋值为11:

然后fun()运行结束,会将申请出来的空间删除掉。会先删除b,再删除a,最后将这块区域删除。

为什么打印了a为10?

是因为上面图中的栈区是fun()的栈区,因为是main中调用fun()的,所以fun()栈区前面紧跟main()的栈区,

打印a的时候其实已经运行完fun(),fun()申请的区域都删除了。所以打印a=10实参。

2.对象类型

还是看fun():

当执行到

因为new是开辟内存,会到堆上开辟:

此时默认age = 0 , name = null

这里的g是引用类型/指针/地址,g只占4字节

当运行:

会找到哦堆内存并赋值。

注意:String 不是值类型,是对象。

所以当执行g.name= "少女",会

String对象中char[]就是值类型了。

java的基础数据类型都是值类型,指针也是值类型,因而是直接存到内存,不是存地址去寻址。

当fun()执行完毕就清空。

但是栈清空掉会发现堆上的空间怎么清空【涉及GC机制。】

还有一点提的是main()就存储在方法区。

此处的i也是在方法区。


思考:

在main()就申请了g,在栈上存放了g的地址,在堆上开辟空间并赋值age = 21

运行到fun()就创建了g的副本(形参)其也在栈上存了地址且和main()中的地址指向相同。

当g.age = 22会去找当前栈中p变量寻址去堆上赋值22,然后fun()的栈区销毁。执行

此时是去堆上找,发现是已经修改过的。所以其打印22.

发布了307 篇原创文章 · 获赞 45 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/qq_39969226/article/details/104172499
今日推荐