詳解Java 中程序內(nèi)存的分析
這篇文章將簡(jiǎn)單的說明下當(dāng)我們運(yùn)行Java程序時(shí)JVM(Java虛擬機(jī))的內(nèi)存分配情況。
首先我們先來感觀的認(rèn)識(shí)下幾個(gè)名詞:
1、棧,一般來說,基本數(shù)據(jù)類型直接在棧中分配空間,局部變量(在方法代碼段中定義的變量)也在棧中直接分配空間,當(dāng)局部變量所在方法執(zhí)行完成之后該空間便立刻被JVM回收,還有一種是引用數(shù)據(jù)類型,即我們通常所說的需要用關(guān)鍵字new創(chuàng)建出來的對(duì)象所對(duì)應(yīng)的引用也是在??臻g中,此時(shí),JVM在??臻g中給對(duì)象引用分配了一個(gè)地址空間(相當(dāng)于一個(gè)門牌號(hào),通過這個(gè)門牌號(hào)就可以找到你家),在堆空間中給該引用的對(duì)象分配一個(gè)空間,??臻g中的地址引用指向了堆空間中的對(duì)象區(qū)(通過門牌號(hào)找住址);
2、堆,一般用來存放用關(guān)鍵字new出來的數(shù)據(jù)。
接下來我們?cè)偻ㄟ^一段程序來直觀感受下程序運(yùn)行時(shí)JVM的內(nèi)存情況,
package demo;
public class Student {
private String name;
private int age;
public void study() {
System.out.println("I love study!");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
package demo;
public class StudentDemo {
public static void main(String[] args) {
Student student = new Student();
System.out.println(student.getName() + ":" + student.getAge());
student.setName("John");
student.setAge(23);
System.out.println(student.getName() + ":" + student.getAge());
student.study();
Student student2 = student;
student2.setName("Jack");
student2.setAge(25);
System.out.println(student2.getName() + ":" + student2.getAge());
System.out.println(student.getName() + ":" + student.getAge());
}
}
當(dāng)我們運(yùn)行程序時(shí),JVM會(huì)把Student類與StudentDemo類編譯完然后加載到JVM中一個(gè)叫方法區(qū)的地方,類的成員變量與成員方法也被加載到方法區(qū)中,此時(shí)內(nèi)存模型如下

可以看到study方法右邊各有一個(gè)16進(jìn)制的標(biāo)記,而name與age變量沒有,這是因?yàn)槊總€(gè)對(duì)象都有各自的成員變量,而類中的成員方法卻可以被每個(gè)對(duì)象所共用,為了節(jié)省內(nèi)存空間,JVM為方法分配了該標(biāo)記(也叫內(nèi)存地址)便于每個(gè)new出來的對(duì)象查找調(diào)用,接著JVM會(huì)自動(dòng)尋找main方法,在棧中為main方法申請(qǐng)一個(gè)空間,這個(gè)過程也叫入棧,然后執(zhí)行我們Student類中第5行代碼,這時(shí)候,JVM在堆空間中分配一塊內(nèi)存給Student對(duì)象,并為其分配一個(gè)內(nèi)存地址(如果對(duì)象的成員變量沒有賦值,則JVM會(huì)為變量賦初始值),在棧中分配一塊內(nèi)存空間用于指向堆空間中的Student對(duì)象區(qū)的內(nèi)存地址,此時(shí)內(nèi)存模型如下

接著看代碼第8行與第9行,程序?yàn)閟tudent對(duì)象的成員變量賦值,JVM會(huì)根據(jù)student所指向的地址在堆內(nèi)存中尋找Student類的變量,并為變量賦新的值

第12行,這時(shí)student對(duì)象調(diào)用study方法,JVM在棧空間中為study方法申請(qǐng)了一塊內(nèi)存空間

study方法執(zhí)行完后,立即釋放??臻g,代碼第14行,student2對(duì)象的引用指向了student所指向的地址

代碼15與16行,為student2的變量賦值,由于student2與student指向了同一個(gè)地方,所以這時(shí)student對(duì)象中變量的值也被改變

到這,main方法中所有代碼執(zhí)行完畢,main方法所占用的棧空間也被回收,而堆空間等待GC回收

代碼執(zhí)行結(jié)果如下:
null:0 John:23 I love study! Jack:25 Jack:25
感謝閱讀,希望能幫助到大家,謝謝大家對(duì)本站的支持!
相關(guān)文章
Java實(shí)現(xiàn)簡(jiǎn)易Web服務(wù)器
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)簡(jiǎn)易Web服務(wù)器的相關(guān)方法,想要制作Web服務(wù)器的朋友可以參考本文2016-02-02
SpringBoot 集成 Kettle的實(shí)現(xiàn)示例
本文主要介紹了SpringBoot 集成 Kettle的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2025-01-01
MyBatis 參數(shù)類型為String時(shí)常見問題及解決方法
這篇文章主要介紹了MyBatis 參數(shù)類型為String時(shí)常見問題及解決方法,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-03-03
java計(jì)算兩個(gè)日期之前的天數(shù)實(shí)例(排除節(jié)假日和周末)
下面小編就為大家?guī)硪黄猨ava計(jì)算兩個(gè)日期之前的天數(shù)實(shí)例(排除節(jié)假日和周末)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-07-07
Java的關(guān)鍵字與標(biāo)識(shí)符小結(jié)
這篇文章主要介紹了Java的關(guān)鍵字與標(biāo)識(shí)符,總結(jié)整理了Java各種常見的關(guān)鍵字與標(biāo)識(shí)符功能、用法及操作注意事項(xiàng),需要的朋友可以參考下2020-04-04

