日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

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

發布時間:2023/12/3 java 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java 中把声明变量的语句如果写在循环体内,每次执行时栈内存中的变量和数据是如何变化的? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

問題一:如下面的代碼示例 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 中把声明变量的语句如果写在循环体内,每次执行时栈内存中的变量和数据是如何变化的?的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。