2024年最全从JVM底层原理分析数值交换那些事·Java大数据高级架构师,2024年最新大数据开发多进程从头讲到尾

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

public static void main(String[] args) {

int a = 1, b = 2;

swapInt(a, b);

System.out.println(“a=” + a + " , b=" + b);

}

private static void swapInt(int a, int b) {

int temp = a;

a = b;

b = temp;

}

结果估计大家都知道,a和b并没有交换:

integerA=1 , integerB=2

但是原因呢?先看这张图,先来说说Java虚拟机的结构:

从JVM底层原理分析数值交换那些事

运行时区域主要分为:

  • 线程私有:

  • 程序计数器:Program Count Register,线程私有,没有垃圾回收

  • 虚拟机栈:VM Stack,线程私有,没有垃圾回收

  • 本地方法栈:Native Method Stack,线程私有,没有垃圾回收

  • 线程共享:

  • 方法区:Method Area,以HotSpot为例,JDK1.8后元空间取代方法区,有垃圾回收。

  • 堆:Heap,垃圾回收最重要的地方。

和这个代码相关的主要是虚拟机栈,也叫方法栈,是每一个线程私有的。

生命周期和线程一样,主要是记录该线程Java方法执行的内存模型。虚拟机栈里面放着好多栈帧注意虚拟机栈,对应是Java方法,不包括本地方法。

一个Java方法执行会创建一个栈帧,一个栈帧主要存储:

  • 局部变量表

  • 操作数栈

  • 动态链接

  • 方法出口

每一个方法调用的时候,就相当于将一个栈帧放到虚拟机栈中(入栈),方法执行完成的时候,就是对应着将该栈帧从虚拟机栈中弹出(出栈)。

每一个线程有一个自己的虚拟机栈,这样就不会混起来,如果不是线程独立的话,会造成调用混乱。

大家平时说的java内存分为堆和栈,其实就是为了简便的不太严谨的说法,他们说的栈一般是指虚拟机栈,或者虚拟机栈里面的局部变量表。

局部变量表一般存放着以下数据:

  • 基本数据类型(boolean,byte,char,short,int,float,long,double)

  • 对象引用(reference类型,不一定是对象本身,可能是一个对象起始地址的引用指针,或者一个代表对象的句柄,或者与对象相关的位置)

  • returAddress(指向了一条字节码指令的地址)

局部变量表内存大小编译期间确定,运行期间不会变化。空间衡量我们叫Slot(局部变量空间)。64位的long和double会占用2个Slot,其他的数据类型占用1个Slot。

上面的方法调用的时候,实际上栈帧是这样的,调用main()函数的时候,会往虚拟机栈里面放一个栈帧,栈帧里面我们主要关注局部变量表,传入的参数也会当成局部变量,所以第一个局部变量就是参数args,由于这个是static方法,也就是类方法,所以不会有当前对象的指针。

从JVM底层原理分析数值交换那些事

如果是普通方法,那么局部变量表里面会多出一个局部变量this。

如何证明这个东西真的存在呢?我们大概看看字节码,因为局部变量在编译的时候就确定了,运行期不会变化的。下面是IDEA插件jclasslib查看的:

从JVM底层原理分析数值交换那些事

上面的图,我们在main()方法的局部变量表中,确实看到了三个变量:args,a,b。

那在main()方法里面调用了swapInt(a, b)呢?

那堆栈里面就会放入swapInt(a,b)的栈帧,相当于把a和b局部变量复制了一份,变成下面这样,由于里面一共有三个局部变量:

  • a:参数

  • b:参数

  • temp:函数内临时变量

a和b交换之后,其实swapInt(a,b)的栈帧变了,a变为2,b变为1,但是main()栈帧的a和b并没有变。

从JVM底层原理分析数值交换那些事

那同样来从字节码看,会发现确实有3个局部变量在局部变量表内,并且他们的数值都是int类型。

从JVM底层原理分析数值交换那些事

而swap(a,b)执行结束之后,该方法的堆栈会被弹出虚拟机栈,此时虚拟机栈又剩下main()方法的栈帧,由于基础数据类型的数值相当于存在局部变量中,swap(a,b)栈帧中的局部变量不会影响main()方法的栈帧中的局部变量,所以,就算你在swap(a,b)中交换了,也不会变。

从JVM底层原理分析数值交换那些事

基础包装数据类型交换

==========

将上面的数据类型换成包装类型,也就是Integer对象,结果会如何呢?

public static void main(String[] args) {

Integer a = 1, b = 2;

swapInteger(a, b);

System.out.println(“a=” + a + " , b=" + b);

}

private static void swapInteger(Integer a, Integer b) {

Integer temp = a;

a = b;

b = temp;

}

结果还是一样,交换无效:

a=1 , b=2

这个怎么解释呢?

对象类型已经不是基础数据类型了,局部变量表里面的变量存的不是数值,而是对象的引用了。先用jclasslib查看一下字节码里面的局部变量表,发现其实和上面差不多,只是描述符变了,从int变成Integer。

从JVM底层原理分析数值交换那些事

从JVM底层原理分析数值交换那些事

但是和基础数据类型不同的是,局部变量里面存在的其实是堆里面真实的对象的引用地址,通过这个地址可以找到对象,比如,执行main()函数的时候,虚拟机栈如下:

假设 a 里面记录的是 1001 ,去堆里面找地址为 1001 的对象,对象里面存了数值1。b 里面记录的是 1002 ,去堆里面找地址为 1002 的对象,对象里面存了数值2。

从JVM底层原理分析数值交换那些事

而执行swapInteger(a,b)的时候,但是还没有交换的时候,相当于把 局部变量复制了一份:

从JVM底层原理分析数值交换那些事

而两者交换之后,其实是SwapInteger(a,b)栈帧中的a里面存的地址引用变了,指向了b,但是b里面的,指向了a。

从JVM底层原理分析数值交换那些事

img
img
img

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

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

需要这份系统化资料的朋友,可以戳这里获取

[外链图片转存中…(img-XnsgPINr-1715639445340)]
[外链图片转存中…(img-w5O2oMsp-1715639445340)]

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

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

需要这份系统化资料的朋友,可以戳这里获取

  • 9
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值