日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

java进出栈_JVM函数调用:Java出入栈

發(fā)布時間:2025/3/20 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java进出栈_JVM函数调用:Java出入栈 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

JVM函數(shù)調(diào)用:Java出入棧

JVM函數(shù)調(diào)用:Java出入棧

目錄

局部變量表

索引復(fù)用

垃圾回收

棧數(shù)據(jù)區(qū)

棧上分配

線程作為系統(tǒng)運算調(diào)度的最小單位,在JVM中線程的行為體現(xiàn)就是函數(shù)調(diào)用,函數(shù)調(diào)用中數(shù)據(jù)的傳遞就是通過Java棧,Java棧顧名思義有著和數(shù)據(jù)結(jié)構(gòu)中“棧”相似的屬性,后進(jìn)先出,出棧入棧,棧中保存的是棧幀,當(dāng)JVM發(fā)生函數(shù)調(diào)用時,就會有一個棧幀被壓入Java棧,當(dāng)函數(shù)調(diào)用結(jié)束后,再從棧中彈出棧幀,當(dāng)前正在執(zhí)行的函數(shù)其對應(yīng)的棧幀位于棧頂處,且保存有當(dāng)前函數(shù)的局部變量表和棧數(shù)據(jù)區(qū)(保存一些中間結(jié)果等數(shù)據(jù))。在函數(shù)返回,也就是有棧幀要從Java棧中彈出時,正常的情況是函數(shù)通過return返回,此時棧幀正常彈出,如果函數(shù)調(diào)用出現(xiàn)問題無法正常返回,則拋出異常,舉個例子:我們每一次函數(shù)調(diào)用時都會對Java棧進(jìn)行入棧操作,棧空間是一定的,隨著不斷入棧操作,例如遞歸函數(shù)調(diào)用,棧空間變得越來越小,最后達(dá)到最大可用深度時,就會拋出棧溢出異常,所以有時我們遞歸函數(shù)調(diào)用過程中出現(xiàn)的“StackOverflowError”,就是棧空間因為某些原因被占滿了導(dǎo)致的。

局部變量表

函數(shù)對應(yīng)的棧幀中有一個局部變量表,里面保存了調(diào)用函數(shù)的局部變量,參數(shù)等,這些參數(shù)和變量是跟著函數(shù)走的,只在當(dāng)前函數(shù)調(diào)用中有效,函數(shù)調(diào)用結(jié)束后,棧幀就會彈出Java棧,局部變量表也就隨之被銷毀。來看一個簡單的例子:

draw()方法中有3個入?yún)⒑?個局部變量,它們都是int數(shù)據(jù)類型,一個占用24個字節(jié)內(nèi)存空間,在32位操作系統(tǒng)中每4個字節(jié)為一個字,所以在局部變量表中,函數(shù)draw()的局部變量一共占6個字。

從上圖可以看到,Maximum local variables表示最大局部變量表大小為6個字。

索引復(fù)用

詳細(xì)點開draw()函數(shù)中的局部變量表,可以看到一些更詳細(xì)的屬性,例如每一個變量的索引index,變量名name和數(shù)據(jù)類型descriptor等。

局部變量表中的索引是可以進(jìn)行復(fù)用的,以次來節(jié)省Java棧空間,具體的復(fù)用方式是這樣,假設(shè)我們定義了一個局部變量i,當(dāng)程序運行到i離開其作用域后,再定義的其他變量可能就會復(fù)用i變量的索引,具體看個例子:

package cell;

public class Cell {

private static boolean tag = true;

public void example1() {

int i = 9527;

System.out.println("i = " + i);

int s = 9527;

}

public void example2() {

if (tag) {

int i = 9527;

System.out.println("i = " + i);

}

int s = 9527;

}

}

程序中有兩個方法,example1()中定義的變量i和變量s作用域都是一樣的,直到example1()方法的結(jié)束,所以兩者的索引沒有辦法復(fù)用。example2()方法中,局部變量i在第16行后就離開了作用域范圍,那么后續(xù)定義的局部變量s可以復(fù)用它的索引,從局部變量表里看,的確是這樣的:

可以看到,方法example1()中局部變量i和s的所有不同,分別是1和2,而到了方法example2()中,局部變量i和s的所有都一樣是1。

垃圾回收

索引復(fù)用有時也會對JVM的垃圾回收產(chǎn)生影響,例如某一個變量i,雖然離開了自己的作用域,但是它之前指向了某一對象,使得變量i仍然存在于局部變量表中,導(dǎo)致變量i指向的對象無法被回收如果變量i指向了某一對象,i離開了作用域后,其索引被后面定義的局部變量所服用了,那么變量i也會被銷毀掉,其指向的對象也就能被正常GC,看一個例子:

public void example1() {

byte[] buffer = new byte[2*1024*1024];

System.gc();

}

public void example2() {

byte[] buffer = new byte[2*1024*1024];

buffer = null;

System.gc();

}

public void example3() {

boolean tag = true;

if (tag) {

byte[] buffer = new byte[2*1024*1024];

}

System.gc();

}

public void example4() {

boolean tag = true;

if (tag) {

byte[] buffer = new byte[2*1024*1024];

}

int i = 9527;

System.gc();

}

上面的程序中,4個方法,第一個example1()中,首先定義byte數(shù)組,申請2MB大小的空間,之后立刻進(jìn)行GC,回收該數(shù)組對象,但是注意,此時因為局部變量buffer強引用了這塊內(nèi)存空間,所以gc暫時無法對其進(jìn)行回收。到example2(),在為byte數(shù)組申請空間,并用局部變量buffer引用這塊區(qū)域后,顯示將buffer置為null,這樣buffer就不會強引用這塊內(nèi)存空間,之后再進(jìn)行GC就可以成功回收。example3()中,我們讓局部變量buffer作用在if語句中,當(dāng)if語句結(jié)束,buffer離開了它的作用域后,我們再進(jìn)行GC,此時因為變量buffer還存在于局部變量表中,所以它的引用還是有效的,GC無法對其引用的空間進(jìn)行回收,解決的辦法來看example4()方法。在example4()中,buffer離開其作用域后,我們再聲明另一個局部變量i,讓它來復(fù)用變量buffer的索引,,這樣buffer變量就真正被替代銷毀了,并且沒有其他變量引用這片內(nèi)存區(qū)域,之后再進(jìn)行GC,可以成功進(jìn)行回收。

棧數(shù)據(jù)區(qū)

Java棧中局部變量表上面簡單總結(jié)了一下,除了局部便變量表,還有棧數(shù)據(jù)區(qū),分為虛擬機棧和本地方法棧,虛擬機棧存放就是棧幀,Java方法運行時所需要的數(shù)據(jù),本地方法棧存放的是JVM調(diào)用的本地方法。

棧上分配

上面說的棧數(shù)據(jù)區(qū)中,虛擬機棧和本地方法棧都是線程獨占的,對于一些線程私有的,不能被其他線程訪問的對象,JVM可以把它們分配在棧上,這樣當(dāng)函數(shù)調(diào)用結(jié)束后就會自行出棧銷毀,不需要GC來進(jìn)行回收,好處就是提高了性能。

private static People p;

public static void initPeople() {

p = new People();

p.name = "Alex";

p.age = 20;

}

上面代碼中People類對象p是一個逃逸的對象,因為它是類的成員變量,可能會被其他線程訪問到,所以虛擬機會把它分配到堆上,而不是線程私有的棧數(shù)據(jù)區(qū)中。如果我們把它改成非逃逸的對象:

public static void initPeople() {

People p = new People();

p.name = "Alex";

p.age = 20;

}

把對象p改成局部變量的方式,且initPeople()方法也沒有將其返回出去,那么該對象p沒有發(fā)生逃逸,虛擬機就會將它分配到棧數(shù)據(jù)區(qū)中。

JVM函數(shù)調(diào)用:Java出入棧相關(guān)教程

總結(jié)

以上是生活随笔為你收集整理的java进出栈_JVM函数调用:Java出入栈的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。