黎梨苗 劉欣
摘 要:Java程序中,java虛擬機(jī)將內(nèi)存分成了兩大部分,每部分的功能不同,這與我們通常所說(shuō)的內(nèi)存有著一定的區(qū)別。那么,java虛擬機(jī)是如何進(jìn)行內(nèi)存的分功的呢?本文將結(jié)合簡(jiǎn)單實(shí)例對(duì)java程序中的內(nèi)存進(jìn)行詳細(xì)解析。
關(guān)鍵詞:java虛擬機(jī)內(nèi)存棧內(nèi)存堆內(nèi)存
Java程序中的內(nèi)存分為兩大部分:一部分叫做棧(Stack)內(nèi)存,另一部分叫堆(heap)內(nèi)存。棧內(nèi)存用來(lái)存放基本數(shù)據(jù)類(lèi)型和引用數(shù)據(jù),基本數(shù)據(jù)類(lèi)型如int,short,byte,float等;引用數(shù)據(jù)類(lèi)型如類(lèi),接口,注解等。堆內(nèi)存用來(lái)存放類(lèi)中的實(shí)例化對(duì)象即用new關(guān)鍵字創(chuàng)建的對(duì)象,如 new animal(),這個(gè)數(shù)據(jù)就存放堆內(nèi)存里。通過(guò)一個(gè)簡(jiǎn)單實(shí)例對(duì)兩部分內(nèi)存做詳細(xì)分析。[1]
一、簡(jiǎn)單實(shí)例
class Student{
int age;String name;
Student (int age,String name){
this age=age;String name=name;}
void listening(){
System.out.print(“學(xué)生正在聽(tīng)課”);}
public static void main(String[] args){
Student stu1=new Student(8,”張三”);
Student stu1=new Student(12,”李四”);
stu1.listening();}}
二、實(shí)例內(nèi)存分配解析
上述實(shí)例中,定義了兩個(gè)基本數(shù)據(jù)類(lèi)型的變量age與name;一個(gè)一般方法;在主函數(shù)內(nèi)創(chuàng)建了兩個(gè)對(duì)象。內(nèi)存分配解析如下:
棧內(nèi)存用來(lái)存放基本數(shù)據(jù)類(lèi)型的變量及對(duì)象的引用地址,在實(shí)例中的基本數(shù)據(jù)類(lèi)型為int age、String name; 對(duì)象的引用為 Student stu1、Student stu2.而堆內(nèi)存用來(lái)存放new出來(lái)的對(duì)象即存放上例中的new Student(8,”張三”)與new Student(12,”李四”),如圖中所示。另外,通常在堆內(nèi)存又細(xì)分出一塊內(nèi)存空間叫常量池,用來(lái)存放不常改變的量,如static修飾的量,final修飾的量,字符串常量及方法,顯然,常量池里所存放的內(nèi)容具有所有實(shí)例共享的特征。實(shí)例內(nèi)存分配如圖1所示。[2]
三、內(nèi)存運(yùn)行機(jī)制
在講內(nèi)存運(yùn)行機(jī)制之前,我們首先必須了解JVM即Java虛擬機(jī),Java程序是在JVM上運(yùn)行的,它是連接操作系統(tǒng)與Java程序之間的紐帶,Java程序有個(gè)特點(diǎn)“一次編譯,到處運(yùn)行”,這正是JVM所起的作用,體現(xiàn)了Java的平臺(tái)無(wú)關(guān)性,可見(jiàn),JVM在Java程序運(yùn)行中起著至關(guān)重要的作用,程序的內(nèi)存分配都是在JVM中進(jìn)行?,F(xiàn)結(jié)合上述簡(jiǎn)單實(shí)例將Java的內(nèi)存運(yùn)行機(jī)制講述如下:
計(jì)算機(jī)把class student整個(gè)程序信息調(diào)入計(jì)算機(jī)內(nèi)存,一旦運(yùn)行程序時(shí),JVM開(kāi)始對(duì)class student整個(gè)信息進(jìn)行內(nèi)存分配;
1. 程序運(yùn)行時(shí),JVM自動(dòng)尋找main方法,執(zhí)行第一句代碼,創(chuàng)建兩個(gè)student類(lèi)的對(duì)象,在棧中分配一塊內(nèi)存,存放兩個(gè)指向堆內(nèi)存的對(duì)象指針215346和140345。
2.JVM讀到下面兩條語(yǔ)句時(shí),
Student stu1=new Student(8,”張三”);
Student stu1=new Student(12,”李四”);
檢測(cè)到age,name是局部變量,因此會(huì)把a(bǔ)ge,name放在棧中,把對(duì)象指針指向堆內(nèi)存的內(nèi)容即把相應(yīng)的“8,張三”與“12,李四”賦給age與name.[3]
3.當(dāng)上面兩條語(yǔ)句執(zhí)行完了,JVM立即釋放變量ageg與name;但stu1與stu2還在堆中,并沒(méi)有釋放掉,因?yàn)榭赡苓€有其他變量指向這兩個(gè)變量。
4.JVM繼續(xù)讀取語(yǔ)句stu1.listening();這時(shí)從常量池中調(diào)用listening()方法給stu1對(duì)象來(lái)完成操作,JVM完成對(duì)象stu1對(duì)listening()方法的算法計(jì)算。由于listening()方法是存放于常量池中供所有類(lèi)對(duì)象共享的,因此,JVM運(yùn)行完語(yǔ)句stu1.listening()后,listening方法依舊在常量池中。
以上就是Java中內(nèi)存機(jī)制運(yùn)行的介紹。
結(jié)語(yǔ)
棧內(nèi)存的數(shù)據(jù)和堆內(nèi)存的數(shù)據(jù)不是同步釋放的。方法結(jié)束時(shí),棧中的局部變量立即釋放,但是堆中對(duì)象不一定釋放。因?yàn)榭赡苡衅渌兞恳仓赶蛄诉@個(gè)對(duì)象,直到棧中沒(méi)有變量指向堆中的對(duì)象時(shí),它才釋放,并且還不是馬上釋放,要等垃圾回收掃描時(shí)才可以被釋放。
參考文獻(xiàn)
[1]章婧,盧凱,周旭,Java內(nèi)存行為研究,小型微型計(jì)算機(jī)系統(tǒng),2011, 32(8):1617-1621.
[2]李杰文,Java程序內(nèi)存使用分析技術(shù)研究,中國(guó)礦業(yè)大學(xué),2016,10(12):32-37.
[3]彭天昊,JAVA語(yǔ)言?xún)?nèi)存分配的探討,凱里學(xué)院學(xué)報(bào),2009, 27(6):93-95.