一个Java类在运行时候,变量是怎么在JVM中分布的呢?

凯哥(凯哥Java:kaigejava)希望通过本文学习,大家对Java虚拟机运行时数据区域有更深的了解

我们写的代码在JVM中是怎么存在的?

==================

1:我们现在看看总体Java运行时数据模型:

=========================================================================================================================================================================================================================

2:我们来看看下面这段代码,执行的时候,在JVM中数据存放:

上面代码很简单,那么对应的变量、对象等在内存中都是怎么分配的呢?

2.1:方法区

=======

注:在JDK1.8之后,方法区被元空间替换了。

方法区:用来存放的是类的信息、常量、静态变量等。该区域也是各个线程共享的内存区域。

根据Java虚拟机规范中的规定,当方法去无法满足内存分配的时候,会抛出:OutOfMemoryError异常的。

根据上面的 定义,我们可以知道比如我们JvmDemo.class信息、static string str=“jvmDemo”是在方法区存放的。

对应咱们代码,方法区存放的如下图:

2.2:堆区

======

堆区是JVM所管理的内存中的最大的一块区域。该区域是所有线程共享的一块内存区域。该区域空间在虚拟机启动的时候就被创建了(-Xms的设置。后面凯哥(凯哥Java:kaigejava)也会详细讲解的)。

此区域的目的是存放对象实例的。几乎所有的对象实例都是在这里分配的。Java虚拟机规范中是这么描述的:所有的对象的实例以及数组都要在堆上分配。

堆区是垃圾收集器管理的主要区域(后面凯哥(凯哥Java:kaigejava)也会详细讲解的).

堆区空间,在物理上可以不是连续的内存空间,只要在逻辑上是连续的即可。如果堆没有内存完成实例分配,并且堆也无法在扩展的时候,将会抛出异常:OutOfMemoryError。这个大家很熟悉吧。

根据上面定义的,我们可以知道,上面代码中Son son = new Son(); 这行代码创建的实例对象是存放在堆区的。

2.3:程序计数器

=========

程序计数器的作用可以看做是当前线程所执行的字节码的行号指示器。字节码解释器在工作的时候,时候通过改变计数器的值来选择接下来要执行的字节码指令的。

同时我们都知道,当多线程的时候,Java虚拟机是通过线程轮流切换分配处理器执行时间的方式来实现的。在任何一个确定的时刻一个处理器只会执行一条线程中的指令。因此,为了解决多个线程在切换后,能够迅速恢复到切换前执行的位置,每个线程都需要有个独立的程序计数器,各个线程直接的计数器互不影响,独立存储的。一般称这类内存区域为:"线程私有"的内存。当线程正在执行的一个方法是Native的,这种情况下,计数器的值就是undefined了。这个区域也是Java虚拟机内存区域中唯一一个没有OOM的区域。

根据上面描述,我们可以知道,我们自己编写的*.java文件要想被执行,需要被编译成*.class的字节码文件。字节码文件对应各种字节码指令。比如我们上面JvmDemo的字节码文件:

从上面截图,我们可以看到,行号是0,3,4,7,8这样的。程序计数器就是记录这些行号的

我们也可以使用idea的插件,来查看我们JvmDemo的相关信息:

2.4:虚拟机栈

========

Java虚拟机栈,也是线程私有的。其生命周期与线程相同,当一个线程运行结束后,对应的虚拟机栈也结束。

虚拟机栈是Java方法执行的内存模型:即每个方法被执行的时候,都会被同时创建一个栈帧(Stack Frame),这个栈帧是用来存放方法局部变量表、操作栈、动态链接、方法出口等信息。每一个方法被调用直到其执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈和出栈的过程。

比如:我们上面代码执行的时候,执行main方法的时候,主线程就会把main方法压入到虚拟机栈中,当执行到add方法的时候,add方法就被压入到栈中了。当执行完add方法后,add方法就被从虚拟机栈中弹出,这个时候add对应的栈帧也销毁。

虚拟机栈帧如下图:

局部变量存放:各种基本数据类型、对象引用和返回类型

八大基本数据类型:boolean、byte、char、short、init、float、long、double;

对象引用:reference类型。这里是存放的是对象在对内存中的地址值。不等同于对象自身的。根据不同的虚拟机的实现,这个指向可能是指向了对象起始地址的引用指针,也有可能是指向了对象对象的句柄或其他对象与其他对象的位置;

返回类型:returnAddress类型。指向一条字节码指令地址。

扩展:long类型和double类型的数据会占用2个局部变量空间。其他6个数据类型占用1个。

局部变量表所消耗的内存空间在编译期间就完成了分配,当进入一个方法的时候,这个方法需要在栈帧中分配多大的局部变量空间是完全确定的。在方法的运行期间,不会改变该区域空间大小的。
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

总结

对于面试还是要好好准备的,尤其是有些问题还是很容易挖坑的,例如你为什么离开现在的公司(你当然不应该抱怨现在的公司有哪些不好的地方,更多的应该表明自己想要寻找更好的发展机会,自己的一些现实因素,比如对于我而言是现在应聘的公司离自己的家更近,又或者是自己工作到达了迷茫期,想跳出迷茫期等等)

image

Java面试精选题、架构实战文档

整理不易,觉得有帮助的朋友可以帮忙点赞分享支持一下小编~

你的支持,我的动力;祝各位前程似锦,offer不断!
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
帮助的朋友可以帮忙点赞分享支持一下小编~**

你的支持,我的动力;祝各位前程似锦,offer不断!
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 13
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值