问题一:如下面的代码示例 1,JVM 是不是会反复回收旧的变量 a 再重新创建新的变量 a 呢?还是旧的变量 a 一直保留在栈内,只是反复赋值 0 而已呢?

代码示例 1:

while (true) {int a = 0;
a = 5;
}

问题二:如下面的代码示例 2,循环体内的引用数据类型变量 p3 是否会先回收再新建,还是保留旧的变量 p3,只是反复对其赋值而已呢?

代码示例 2:

Person p1 = new Person();Person p2 = new Person();while (true) {Person p3 = p1;p3 = p2;}

正确答案:旧变量依旧保留在栈内,只是反复赋值。

基本类型变量 a 和引用类型变量 p3 都不会因为声明变量的语句在循环体内而不断地重新创建,变量一直存在栈内存中,只是循环的赋值而已,只是循环地对变量 a 和变量 p3 读写数据而已。

参考答案:

首先,先明白一个概念,什么是“回收”?

大家都知道,JVM的内存结构有两个主要的区域:堆内存和栈内存。

那么回收也是有相应的两个层面的:

  • 在堆内存里面发生的回收:由垃圾回收器进行回收,会把不再可用的对象进行回收。
  • 在栈内存里面发生的回收:栈内存是由栈帧组成的,局部变量都是在栈帧里面定义的,所以局部变量的回收,是随着栈帧的销毁而被回收的。而栈帧的销毁,是在方法调用完成之后。

在弄清楚“回收”的概念之后,再回到问题。

先看问题1:
这段代码里面,很明显,变量a是一个局部变量,而且是原始类型的局部变量,所以它的内存分配是在栈上,确切地说是在栈帧里面的局部变量表里面。而局部变量表这个东西,是在编译期间就确定的,它类似一个数组,里面包含了一些“槽位”来存放局部变量。那么,a这个变量,就是在局部变量表中的某一个槽位里面。并且a只会占用一个槽位,while循环里面来来回回也是对这一个槽位的里面进行读写。这个严格来说,算不上是“回收”。

再看问题2:
问题2和问题1基本上一样的,在while 循环体里面只是对局部变量表的一个槽位来进行读写。和问题1有点区别的地方只是,p1和p2两个对象都是引用类型的,他们分别指向了堆内存的两个对象,并且这两个位于堆内存中的对象是没有变化的。

再看问题3:
顺着题主的思路,我猜测应该还有一种情况也是题主关心的,就是下面这种情况:

while (true) {Person p1 = new Person();Person p2 = p1;
}

在这种情况里面,while 循环体里面会有两个局部变量p1和p2,他们也会在局部变量表中占用两个槽位。在每一次循环中,new Person() 这个语句都会在堆内存创建一个新的对象,并且把p1变量指向这个新建的对象,随后p2 也会指向相同的对象。所以这个例子里面,堆内存中会在不停地创建对象,而这个大量对象的创建,会触发到堆内存里面的垃圾回收,垃圾回收器会把这些创建后又没使用的一大堆Person对象给回收掉。所以这个过程就是在 “不停创建” – “垃圾回收”之间来回切换,进而导致内存的占用会忽上忽下,这种现象也被称为“内存抖动”。“内存抖动”是比较耗性能的,应该在实际应用中尽量避免。

综上,题目中的两个问题,简单来说就是:while语句中的变量都是在局部变量表中占用了一个槽位,并且对这个槽位反复读写,所以称不上是“回收”。

参考地址:https://www.zhihu.com/question/439157488

Java 中把声明变量的语句如果写在循环体内,每次执行时栈内存中的变量和数据是如何变化的?相关推荐

  1. 【C 语言】结构体 ( 结构体类型定义 | 结构体类型别名 | 声明结构体变量的三种方法 | 栈内存中声明结构体变量 | 定义隐式结构体时声明变量 | 定义普通结构体时声明变量 )

    文章目录 一.结构体类型定义 二.结构体类型别名 三.结构体类型变量声明 1.使用结构体类型 ( 别名 ) 声明变量 2. 定义隐式结构体时声明变量 3.定义普通结构体时声明变量 二.完整代码示例 一 ...

  2. Java对象运行时在内存中的情况

    Java对象运行时在内存中的情况 您可能已经知道,一旦创建了一个对象,它就只是堆中的一系列字节.您可能对Java对象在内存中的情况感到好奇吗? 1.变量 以下是"Base"(B)类 ...

  3. 查询一个表中所有id字段在另一个表中对应值的SQL语句怎么写?

    编辑器加载中... 查询一个表中所有id字段在另一个表中对应值的SQL语句怎么写?多表联结查询:select rbd.RBDID, rbd.ProductCode,p.ProductCnName,p. ...

  4. LSM树——放弃读能力换取写能力,将多次修改放在内存中形成有序树再统一写入磁盘...

    LSM树(Log-Structured Merge Tree)存储引擎 代表数据库:nessDB.leveldb.hbase等 核心思想的核心就是放弃部分读能力,换取写入的最大化能力.LSM Tree ...

  5. LSM树——放弃读能力换取写能力,将多次修改放在内存中形成有序树再统一写入磁盘,查找复杂度O(k*log(n)),结合bloom filter提高查找性能...

    来自:http://www.open-open.com/lib/view/open1424916275249.html 十年前,谷歌发表了 "BigTable" 的论文,论文中很多 ...

  6. python函数 模块先加载到内存后执行_Python从内存中使用编译后的模块

    在Windows编程的时候,有些时候,我们经常会要使用一些非常规的方法,比如说从内存中加载DLL,然后使用DLL中的函数.于是就思索在用Python的时候是否能够将几个编译好的Pyc合并成一个,然后使 ...

  7. C99中带声明的for语句

    计算整数n的所有正因子之和. C99之前for语句的格式如下: for(表达式1;表达式2;表达式3) 语句 例如: int i; for(i=0;i<n;i++) ... 表达式1是循环开始执 ...

  8. oracle中删除表字段 sql语句怎么写,oracle使用sql语句增加字段示例(sql删除字段语句)...

    添加字段的语法:alter table tablename add (column datatype [default value][null/not null],-.); 修改字段的语法:alter ...

  9. oracle 数据库循环查询语句怎么写,sql循环查询(sql语句循环查询详解)

    sql循环查询(sql语句循环查询详解) 2020-07-24 11:15:51 共10个回答 select*fromawheret_idin('3','4');select*fromawheret_ ...

最新文章

  1. JVM内存调优原则及几种JVM内存调优方法
  2. 转 DevExpress-ASPxPageControl 动态添加 TabPage 内容
  3. stl里面stack的注意事项
  4. 你是一个优秀的IT PRO吗?(下篇)
  5. 移动端AI应用太抢手,高通这次要送开发者20万+的SUV
  6. Python Web开发框架Django
  7. 十-二进制数的最少数目
  8. oseasy还原卡_学校机房管理批量更新软件的问题还原卡、网刻、噢易OSS对比区别...
  9. mac 文字识别软件ocr_树洞OCR文字识别for Mac-树洞OCR文字识别Mac版下载 V1.2.0-PC6苹果网...
  10. python输入直角三角形两条直角边、输出斜边长_用C++输入直角三角形的两条直角边长,调用平方根函数sqrt来求斜边的长度。...
  11. 不确定性Uncertainty
  12. 【计算大于这个整数的最小质数】
  13. (第十三届蓝桥杯省赛)试题J:砍竹子(优先队列+模拟)
  14. 新美域杂志新美域杂志社新美域编辑部2022年第6期目录
  15. vue单页面SEO优化
  16. 区块链网络管理平台WeBASE双节点可视化部署
  17. MOSFet cutoff frequency ( From google)
  18. DSM-830源网荷系统控制终端(源网荷智能互动终端)-新型电力负荷控制终端(电力负荷管理终端装置)-互动式需求侧管理终端-专变采集终端的功能。DSM-830交互式需求侧管理终端(需求侧管理互动式终端
  19. gsoc 任务_gsoc 2020最终报告wikimedia transferpy改进
  20. 学习使用微信小程序动态获取当前时间并实时跳动

热门文章

  1. java 示例_功能Java示例 第5部分–将I / O移到外部
  2. java 错误输入异常_在Java中进行输入验证期间用错误通知替换异常
  3. jpa语法错误_JPA陷阱/错误
  4. hibernate与jpa_将JPA Hibernate与OptaPlanner集成
  5. REST /使用提要发布事件
  6. OpenHub框架进行的异步通信
  7. Java命令行界面(第19部分):jClap
  8. Java数据类型和标识符
  9. java中无法推断类型参数_Java中的推断异常
  10. servlet3.0新特性_查看Servlet 3.0的新增功能