999精品在线视频,手机成人午夜在线视频,久久不卡国产精品无码,中日无码在线观看,成人av手机在线观看,日韩精品亚洲一区中文字幕,亚洲av无码人妻,四虎国产在线观看 ?

變量在Java棧、堆內存中的運用管理分析

2017-04-18 18:08:11陳益楊曉艷
軟件導刊 2017年2期

陳益 楊曉艷

摘要 初次接觸面向對象程序設計,不易弄清楚各種類型變量在內存中是如何分配和管理的。以Java為例,主要介紹基本數據類型一維數組內存模型、引用數據類型數組內存模型、方法調用時變量的內存模型、內部類的內存模型的活動空間。了解對象的屬性和行為在內存中的位置和彼此間的關系,有助于更好地理解程序的編譯原理和運行機制。

關鍵詞 JVM;內存模型;基本類型;引用類型

DOI DOI: 10.11907/rjdk.162172

中圖分類號: TP301

文獻標識碼: A 文章編號 文章編號: 16727800(2017)002002903

0 引言

對于不同的平臺,內存模型通常有所差異。Java虛擬機、Java Virtual Machine(簡稱JVM)的內存模型規范是統一的。Java內存分配時涉及到的區域有:①棧內存(簡稱棧):一般用來存放基本類型的數據和對象的引用,不包括對象自身;②堆內存(簡稱堆):用來存放由new關鍵字創建的對象;③常量池:用來存放常量;④靜態域:用來存放靜態成員;⑤非RAM存儲:一般指硬盤等永久存儲空間;⑥寄存器:由編譯器根據實際需要分配內存區域,用戶在編程中無法控制它。

Java中的變量包括基本類型和引用類型變量兩大類,當用戶在一個類中定義了一個變量,JVM在棧內存中為此變量分配空間大小,對象調用完變量后,Java虛擬機將釋放掉先前為該變量分配的空間[1]。方法中的基本類型變量和對象引用變量,都在方法的棧中被分配空間。棧中主要存放一些基本類型的變量數據和對象引用。也即當用戶在Java中聲明一個變量時,則在棧中為其分配了一塊空間,用來存放變量的值,變量的值可以是數值、false、null等。直接被賦值為數值或false的變量,即是通常Java中規定的8種基本數據類型變量,包括:boolean、byte、char、int、short、long、float、double,它們的值則放在棧中提供給用戶使用;值為null的變量是引用類型的變量,在Java中凡是聲明為數組、類(對象)、字符串、接口等類型的變量都是引用類型變量,在聲明時其默認值也存放在棧中。

由于引用類型變量在聲明時默認值為null,所以要和存放在堆中的對象產生一定聯系,以獲取該對象的首地址信息來替換聲明時的null,這種聯系被形象地稱為指向。建立了堆棧之間的指向,棧中的變量才有了真正的實體,才能被使用。Java中堆棧之間的指向類似于C語音中的指針。Java中的堆是一個運行時的數據區,用來存放由new關鍵字創建的對象和數組,它不需要程序代碼來顯式地釋放內存空間,而是由堆動態地分配內存大小,由JVM虛擬機的自動垃圾回收器來管理那些不再被引用的內存。本文主要介紹引用數據類型變量在內存中的分配狀況。

1 基本數據類型一維數組內存模型

聲明一個一維整形數組變量n,比如int []n,則n的值默認為null,存放在棧中,和其它內存沒有任何交集,內存模型如圖1所示。要想使用n數組變量,則應該創建對象給數組分配大小,給n變量賦予實際意義的值,所賦的值是該數組首元素的地址。在Java中聲明一維整型數組后,由new關鍵字創建對象并為其分配空間,聲明變量和創建對象通常由一步完成。如int []n=new int[3];n的值為數組首元素地址,即n指向數組的首元素,具體做法是將數組首元素的地址放入n變量中,替換n的初始值null。n中有3個能操作的變量,可以給3個變量作賦值操作,如同給任意一個簡單變量賦值操作一樣。如果用戶沒有給3個數組元素初始化,因為3個元素的類型都是整型(數值型),在堆內存中會默認3個元素的值都為0。

內存模型如圖2所示。如n不再指向數組的首元素,即當賦值號兩邊的操作對象之間沒有任何聯系時,n的值再次為null,內存模型如圖3所示。沒有被任何引用類型變量指向的對象是一個匿名對象。

2 引用數據類型數組內存模型

2.1 對象數組類型

聲明一個引用類型的數組變量stu,數組的類型為對象引用型,如Student []stu;與基本整型的一維數組相比,雖然都是引用類型,但數組的類型是對象型,不過值都是一樣為null,對象數組值為null的內存模型和基本類型數組的模型一樣,如圖1所示。用new分配3個長度的空間,Student []stu = new Student[3],因為3個數組元素都為對象型的變量,初始默認值為null,還不能使用,內存模型如圖4所示。要想使用數組中的每個數組元素,需要分別給各個數組元素補充完整信息,如圖5所示。給數組的首元素賦值,有兩個屬性分為姓名“lisi”和年齡“18”,即可使用首元素。

2.2 字符串類型

圖6為字符串對象模型,當用戶聲明一個字符串類型引用變量時,如String s1,變量s在棧內存中被分配空間,其值為null,系統只為變量分配了引用空間,還沒有創建具體對象。當new關鍵字調用構造方法后才創建對象,并將對象的引用賦值給字符串引用類型的變量s1,兩步工作可以合并為一步完成,如s2字符串引用類型變量聲明所示[2]。代碼段如下所示:

class StringDemo

{

public static void main(String args[])

{ Stirng s1;

s1=new Stiring(“def”);

String s2=new String(“def”);

if(s1==s2) System.out.println(“s1==s2”);

else System.out.println(“s1!=s2”);

if(s1.equals(s2)) System.out.println(“s1 equals s2”);

else System.out.println(“s1 not equals s2”);

}

}

先分析源程序的運行結果,程序中兩個if語句描述了字符串等號“= =”和equals方法的功能。String s1=new String("def"); String s2=new String("def"),由字符串String類產生了兩個字符串對象,分別為s1和s2。第一個if語句if(s1= =s2)的結果是s1!=s2,第二個if語句if(s1.equals(s2))的結果是s1 equals s2。分析結果產生的根源要從內存模型來解釋。s1和s2是兩個引用(字符串)類型的變量,當兩個字符串引用類型的變量作“= =”比較時,表面上是比較兩個變量的值,但該值不同于簡單變量的數值,引用類型變量的值實質上指的是地址,它們分別為兩個不同的字符串常量,因此其地址肯定不相等。但兩個變量表示的字符串內容相等,都是“def”,采用equals方法的作用是比較兩個變量代表的內容,如圖6所示。

另外,程序中用來給變量賦值的常量(如數值、字符串等)都位于常量池中。常量池是由編譯器確定被保存在.class文件中的數據信息,里面除了基本數據類型和引用類型的常量外,還包含一些文本形式的符號引用,比如:類、變量、方法及接口的名稱和描述符。對于String類型的常量,它的值存放在常量池中。在JVM中,常量池在內存中是以表的形式存在。對于String類型,有一張固定長度的常量字符串信息表,專門負責存儲文字字符串值,而不存儲符號引用。位于.class字節碼文件中的常量,在運行期間由JVM自行裝載,還具有擴充功能。String類中的intern即是擴充常量池的一個方法。

3 方法調用時變量內存模型

圖7為方法調用模型1,圖8為方法調用模型2,自定義方法中有無參數(方法中的參數稱為形式參數,簡稱形參)都可以。方法中若有參數將帶來程序的靈活性,參數類型由用戶根據具體需要設定。基本數據類型變量之間的值傳遞是簡單的單向傳遞。JVM中傳遞各種類型變量值的方法主要分為3種:①方法的參數為簡單變量,進行單向值傳遞;②方法的參數為數組變量,進行地址傳遞;③方法的參數為對象變量,進行地址傳遞。在如下代碼段中,fn1方法有3個重載的方法,參數分別為整型變量、數組變量和對象變量,試分析程序的運行結果。

class MethodDemo

{ public static void fn1(int x,int y)

{ x=x+y; y=x-y; x=x-y; }

public static void fn2(int[] n)

{ n[0]=n[0]+n[1]; n[1]=n [0]-n[1]; n[0]=n[0]-n[1]; }

public static void fn3(Test p)

{ p.x=p.x+p.y; p.y=p.x-p.y; p.x=p.x-p.y; }

public static void main(String[] args)

{ int x=5,y=7; fn1(x,y); System.out.println("x="+x+”,”+"y="+y);

int[] n=new int[]{5,7}; fn2(n);

System.out.println("x="+n[0]+","+"y="+n[1]);

Test p=new Test(); p.x=5; p.y=7; fn3(p);

System.out.println("x="+x+”,”+"y="+y);?}

}

class Test

{ int x,y;

public String toString()

{ return "x="+x+","+"y="+y;? }

}

由運行結果可知,在Java中,對于方法fn1,簡單變量的值傳遞與其它語言中簡單變量的值傳遞原理一致,都是單向傳遞,傳遞的是值本身,方法調用過程中不會改變原有值,并且JVM中所有的簡單變量都保存在棧內存中,與堆內存沒有聯系,具體如圖7所示;對于方法fn2和fn3,當數組或對象作為方法的參數時,因為傳遞的是地址,地址改變時,原來的值也跟隨改變,具體如圖8所示。

4 內部類內存模型

類的成員除變量和方法外,還可以有另一個成員內部類。內部類(也稱Inner Class)指在一個類中定義的另外一個類。內部類和外部類的定義方式一樣,其擁有自己獨立的屬性和方法,并將它們封裝在一個類中。內部類擁有和方法一樣的訪問權限,可以聲明為public、protected、default和private。內部類將邏輯上相關的一組類組織起來,由外部類(OuterDemo Class)來控制其可見性[3]。代碼如下所示:

class OuerDemo

{

private int n=50;

class Inner

{ void fn2()

{ System.out.println(n); }

}

void fn2()

{ Inner in=new Inner();

in.fn2();

}

}

class Test

{

public static void main(String args[])

{

OuterDemo out=new OuterDemo();

out.fn2();

}

}

編譯后將產生3個.class文件,一個是含有main方法的Test類的Test.class,一個是外部類的OuterDemo.class文件,還有一個是內部類的OuterDemo$ Inner.class文件,運行結果打印輸出為50。程序中將成員變量n的訪問權限設置為私有的(private),檢驗外部類的私有變量n能夠被內部類Inner中的fn2( )方法所訪問。如果私有變量都能被訪問,外部類中其它的訪問權限,共有的、受保護的和友好的則也能被內部類的成員訪問。主要當創建一個內部類對象時,它與外部類對象之間便產生了一種聯系,這種聯系是通過一個特殊變量this搭建的,從而使內部類對象能隨意訪問外部類中的所有成員。具體內存模型如圖9所示。

5 結語

JVM定義了各種變量的內存模型狀態,每個變量都在自己的內存空間中活動,同時又與其它內存建立聯系。Java自動管理棧內存和堆內存,程序員不能直接設置棧內存或堆內存,棧內存中放置基本類型、局部變量和引用變量的值。引用變量存放在棧內存中,對象內容根據創建方式而定,由編譯器事先創建好并存放在常量池中,程序運行時由new調用構造方法創建的對象,存放在堆內存中。 棧的優點是數據共享、存取速度快;缺點是數據大小與生存期必須是確定的,缺少靈活性。

堆內存放置new調用構造方法創建的對象。一旦在堆中產生數組或對象后,可以在棧中聲明一個特殊變量,變量的值等于數組或對象在堆內存中的首地址,棧里聲明的特殊變量則成了數組或對象的引用變量。其實,棧內存中的變量指向堆內存中的對象,可以被理解為JVM中的指針。由于堆內存分配是在程序運行時動態進行的,所以堆內存的存取速度相對于棧內存而言較慢。

String類表示一個字符串,在Java中所有的文字串,例如“abc”都是作為String類的實例來實現的。String類是Java中一個特殊的封裝類,它被聲明為final,用戶不能從String類派生出其它類,一個String類的對象是一個常量,創建之后值不能被改變。

參考文獻:

[1] 耿祥義.Java2實用教程[M].第4版.北京:清華大學出版社,2012.

[2] 張桂珠.JVM面向對象程序設計[M].第3版.北京:北京郵電大學出版社,2010.

[3] 孫鑫.Java無難事[M].北京:電子工業出版社,2004.

[4] 林樹澤.Java完全自學手冊[M].北京:機械工業出版社,2009.

[5] 周志明.深入理解Java虛擬機[M].北京:機械工業出版社,2011.

[6] [美]BRUCE ECKEL.Java編程思想[M].第4版.陳昊鵬,譯.北京:機械工業出版社,2007.

[7] 聶芬.Java中堆與棧的內存分配[J].電腦學習,2010(6):123124.

(責任編輯:杜能鋼)

主站蜘蛛池模板: 91精品国产麻豆国产自产在线| 国产欧美日韩综合一区在线播放| 国产精品亚洲а∨天堂免下载| 国产成人免费高清AⅤ| 人妻熟妇日韩AV在线播放| 911亚洲精品| 欧美国产日韩在线观看| 国产天天射| 在线日韩一区二区| 国产精品极品美女自在线看免费一区二区| 制服丝袜无码每日更新| 亚洲乱码在线播放| 日本草草视频在线观看| 久久久久久午夜精品| 国产精品成人AⅤ在线一二三四| 日韩 欧美 国产 精品 综合| 久久免费视频播放| 精品久久综合1区2区3区激情| 国产亚洲精品91| 欧美h在线观看| 国产成人久久综合777777麻豆| 五月天丁香婷婷综合久久| 亚洲国产日韩视频观看| 国产一区二区三区免费| 人禽伦免费交视频网页播放| 少妇精品网站| 亚洲高清中文字幕在线看不卡| 亚洲首页国产精品丝袜| 91久久偷偷做嫩草影院| 欧美色图第一页| 国产精品第5页| 又大又硬又爽免费视频| 91精品福利自产拍在线观看| 99热这里只有精品在线观看| 欧美精品在线视频观看| 免费国产无遮挡又黄又爽| 91啪在线| 黄色片中文字幕| 刘亦菲一区二区在线观看| 免费在线成人网| 日本一区中文字幕最新在线| 国产91丝袜在线观看| 日韩第一页在线| 久久国产毛片| 国产手机在线ΑⅤ片无码观看| 香蕉久人久人青草青草| 久久a毛片| 国产精品内射视频| 亚洲欧洲美色一区二区三区| 亚洲h视频在线| 青青青草国产| 国产噜噜噜视频在线观看| 亚洲高清中文字幕在线看不卡| 午夜电影在线观看国产1区| 992tv国产人成在线观看| 国产精品手机在线观看你懂的 | 国产精品香蕉| 57pao国产成视频免费播放 | 国产又色又爽又黄| 第九色区aⅴ天堂久久香| 国产草草影院18成年视频| 理论片一区| 91在线播放免费不卡无毒| 一级毛片无毒不卡直接观看| 中国一级特黄视频| 最新国语自产精品视频在| 中文字幕永久视频| 欧美亚洲国产日韩电影在线| 国产在线拍偷自揄拍精品| 不卡无码h在线观看| 国产亚洲视频免费播放| 国产自在线播放| 亚洲福利一区二区三区| 国产成人精品午夜视频'| 久爱午夜精品免费视频| 成人亚洲视频| 2021精品国产自在现线看| 日韩最新中文字幕| 国产区91| AV老司机AV天堂| 免费一级毛片不卡在线播放| 成人午夜在线播放|