【死磕JVM】一道面试题引发的“栈帧”!!!

最近小农的朋友——小勇在找工作,开年来金三银四,都想跳一跳,找个踏(gao)实(xin)点的工作,这不小勇也去面试了,不得不说,现在面试,各种底层各种原理,层出不穷,小勇就遇上了这么一道面试题,因为没有回答好,面试被PASS,让他备受打击,作为大(lao)哥(si)哥(ji)的我,肯定要安慰一下,到底是什么样的面试题,让小勇又一次夭折在面试的路上,好奇怪为什么要说又?简直让人喜极而泣,哈哈哈,言归正传,我们一起来看一下!

话说小勇正襟危坐在面试官面前,这已经是小勇的第五次面试了,前几次都是石沉大海,让小勇有点着急了,但是小勇这一次可是有备而来,之前面试不会的问题,大部分都狠狠的补习了一下,想来这一次问题应该不大。

前面基础问题小勇都回答的有模有样的,面试官一看,基础还算可以,问一点有深度的吧!

面试官:我看你简历上写的熟悉JVM,我给你下面一个题目,先来讲一讲a = a ++; 和a = ++a; 的运行结果各是多少?

public class Test1 { public static void main(String[] args) { int a = 88; a = a++; // a = ++a; System.out.println(a); } }

小勇心想:这不是小菜一碟吗,这我能不知道?
于是小勇轻蔑一笑说:a = a++; 输出结果是 8 ,a = ++a; 是 9
心想我还以为多有难度呢,就这?这种题目给我再来一个吧!

面试官:无动于衷,面无表情的说道,为什么结果是这样的,你知道吗?

小勇:还真来,提高难度了,小样有点东西啊,还好准备了,不然今天就在你这道题上坑住了。
a++ 是先计算 a 在++,在分号结束的才会做a++运算,所以当我们做赋值操作的时候a++ 还是 8,所以赋值给a的时候也是8,只有当分号结束了a++才会是9
++a 是 先计算 ++a ,不管是否在分号结束,这个时候的值就已经是 9 了,所以赋值的时候,a就变成了9,输出结果也就是9了
这下没话说了吧!

面试官摸了一下下巴,缓缓说到:这个操作在JVM内存里面是怎样运行的?

小勇:怎么运行的,这个不是底层原理了吗?剧本不是这么发展的,这块没有了解过。。。。
小勇:支支吾吾说道,这个没有了解过,不太清楚底层的实现

面试官轻蔑一笑说:行,今天面试就先到这里了,有什么事情,人事会通知你的!

小勇:!$%@#&*

不懂就学

听到上面小勇所讲的东西之后,大概了解到,面试官应该是要考他关于运行时数据在内存时候的知识点,不懂就学,遇到事情不要慌,想要真正理解上面的面试题的精髓,我们要做一些前置知识的点缀,首先我们先来看看下面一张图:
类生命周期:

在这里插入图片描述

上图中首先将.class 文件读取到内存,存放在方法区(Perm Gen), 最终产品是Class对象,然后检查是否有正确数据结构,JVM为Class的静态变量分配内存,并设置默认初始值,把Class的二进制数据中的符号引用替换为直接引用,JVM为执行Class 的static 语句块,会先初始化其父类,跑到JVM虚拟机之后呢,会进入到运行时引擎,最后在运行时引擎里面运行,运行的时候在内存里面是一个什么样的情况,这个就是我们要讲的重点——run-time data areas

运行时数据区

Java虚拟机运行时数据区:

在这里插入图片描述

1.1 程序计数器 > 程序计数器是一块较小的内存空间, 它可以看作是当前线程所执行的字节码的行号指示器。由于Java虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的,在任何一个确定的时刻,一个处理器都会只执行一条线程中的指令,因此为了线程切换后都能回复正确的执行位置,每个线程都有一个独立的程序计数器。如果线程正在执行的是一个java方法,这个计数器记录的就是正在执行的虚拟机字节码指令的地址。如果正在执行的是native方法,这个计数器值则为空。

作用:
1、字节码解释器通过改变程序计数器来一次读取指令,从而实现代码的流程控制。比如:顺序执行、选择、循环、异常处理等
2、在多线程的情况下,程序计数器用于记录当前线程线程执行的位置,当线程被切换回来的时候能够知道该线程上次运行到哪里了

特点:

是一块较小的内存空间

线程私有,每一条线程都有一个程序计数器

是唯一不会出现 OutOfMemoryError的内存区域

生命周期随着线程的创建而创建,随着线程的结束而结束

1.2 Java虚拟机栈

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wsszyx.html