亚洲免费av电影一区二区三区,日韩爱爱视频,51精品视频一区二区三区,91视频爱爱,日韩欧美在线播放视频,中文字幕少妇AV,亚洲电影中文字幕,久久久久亚洲av成人网址,久久综合视频网站,国产在线不卡免费播放

        ?

        變量在Java棧、堆內(nèi)存中的運(yùn)用管理分析

        2017-04-18 18:08:11陳益楊曉艷
        軟件導(dǎo)刊 2017年2期

        陳益 楊曉艷

        摘要 初次接觸面向?qū)ο蟪绦蛟O(shè)計(jì),不易弄清楚各種類(lèi)型變量在內(nèi)存中是如何分配和管理的。以Java為例,主要介紹基本數(shù)據(jù)類(lèi)型一維數(shù)組內(nèi)存模型、引用數(shù)據(jù)類(lèi)型數(shù)組內(nèi)存模型、方法調(diào)用時(shí)變量的內(nèi)存模型、內(nèi)部類(lèi)的內(nèi)存模型的活動(dòng)空間。了解對(duì)象的屬性和行為在內(nèi)存中的位置和彼此間的關(guān)系,有助于更好地理解程序的編譯原理和運(yùn)行機(jī)制。

        關(guān)鍵詞 JVM;內(nèi)存模型;基本類(lèi)型;引用類(lèi)型

        DOI DOI: 10.11907/rjdk.162172

        中圖分類(lèi)號(hào): TP301

        文獻(xiàn)標(biāo)識(shí)碼: A 文章編號(hào) 文章編號(hào): 16727800(2017)002002903

        0 引言

        對(duì)于不同的平臺(tái),內(nèi)存模型通常有所差異。Java虛擬機(jī)、Java Virtual Machine(簡(jiǎn)稱(chēng)JVM)的內(nèi)存模型規(guī)范是統(tǒng)一的。Java內(nèi)存分配時(shí)涉及到的區(qū)域有:①棧內(nèi)存(簡(jiǎn)稱(chēng)棧):一般用來(lái)存放基本類(lèi)型的數(shù)據(jù)和對(duì)象的引用,不包括對(duì)象自身;②堆內(nèi)存(簡(jiǎn)稱(chēng)堆):用來(lái)存放由new關(guān)鍵字創(chuàng)建的對(duì)象;③常量池:用來(lái)存放常量;④靜態(tài)域:用來(lái)存放靜態(tài)成員;⑤非RAM存儲(chǔ):一般指硬盤(pán)等永久存儲(chǔ)空間;⑥寄存器:由編譯器根據(jù)實(shí)際需要分配內(nèi)存區(qū)域,用戶(hù)在編程中無(wú)法控制它。

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

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

        1 基本數(shù)據(jù)類(lèi)型一維數(shù)組內(nèi)存模型

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

        內(nèi)存模型如圖2所示。如n不再指向數(shù)組的首元素,即當(dāng)賦值號(hào)兩邊的操作對(duì)象之間沒(méi)有任何聯(lián)系時(shí),n的值再次為null,內(nèi)存模型如圖3所示。沒(méi)有被任何引用類(lèi)型變量指向的對(duì)象是一個(gè)匿名對(duì)象。

        2 引用數(shù)據(jù)類(lèi)型數(shù)組內(nèi)存模型

        2.1 對(duì)象數(shù)組類(lèi)型

        聲明一個(gè)引用類(lèi)型的數(shù)組變量stu,數(shù)組的類(lèi)型為對(duì)象引用型,如Student []stu;與基本整型的一維數(shù)組相比,雖然都是引用類(lèi)型,但數(shù)組的類(lèi)型是對(duì)象型,不過(guò)值都是一樣為null,對(duì)象數(shù)組值為null的內(nèi)存模型和基本類(lèi)型數(shù)組的模型一樣,如圖1所示。用new分配3個(gè)長(zhǎng)度的空間,Student []stu = new Student[3],因?yàn)?個(gè)數(shù)組元素都為對(duì)象型的變量,初始默認(rèn)值為null,還不能使用,內(nèi)存模型如圖4所示。要想使用數(shù)組中的每個(gè)數(shù)組元素,需要分別給各個(gè)數(shù)組元素補(bǔ)充完整信息,如圖5所示。給數(shù)組的首元素賦值,有兩個(gè)屬性分為姓名“l(fā)isi”和年齡“18”,即可使用首元素。

        2.2 字符串類(lèi)型

        圖6為字符串對(duì)象模型,當(dāng)用戶(hù)聲明一個(gè)字符串類(lèi)型引用變量時(shí),如String s1,變量s在棧內(nèi)存中被分配空間,其值為null,系統(tǒng)只為變量分配了引用空間,還沒(méi)有創(chuàng)建具體對(duì)象。當(dāng)new關(guān)鍵字調(diào)用構(gòu)造方法后才創(chuàng)建對(duì)象,并將對(duì)象的引用賦值給字符串引用類(lèi)型的變量s1,兩步工作可以合并為一步完成,如s2字符串引用類(lèi)型變量聲明所示[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”);

        }

        }

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

        另外,程序中用來(lái)給變量賦值的常量(如數(shù)值、字符串等)都位于常量池中。常量池是由編譯器確定被保存在.class文件中的數(shù)據(jù)信息,里面除了基本數(shù)據(jù)類(lèi)型和引用類(lèi)型的常量外,還包含一些文本形式的符號(hào)引用,比如:類(lèi)、變量、方法及接口的名稱(chēng)和描述符。對(duì)于String類(lèi)型的常量,它的值存放在常量池中。在JVM中,常量池在內(nèi)存中是以表的形式存在。對(duì)于String類(lèi)型,有一張固定長(zhǎng)度的常量字符串信息表,專(zhuān)門(mén)負(fù)責(zé)存儲(chǔ)文字字符串值,而不存儲(chǔ)符號(hào)引用。位于.class字節(jié)碼文件中的常量,在運(yùn)行期間由JVM自行裝載,還具有擴(kuò)充功能。String類(lèi)中的intern即是擴(kuò)充常量池的一個(gè)方法。

        3 方法調(diào)用時(shí)變量?jī)?nèi)存模型

        圖7為方法調(diào)用模型1,圖8為方法調(diào)用模型2,自定義方法中有無(wú)參數(shù)(方法中的參數(shù)稱(chēng)為形式參數(shù),簡(jiǎn)稱(chēng)形參)都可以。方法中若有參數(shù)將帶來(lái)程序的靈活性,參數(shù)類(lèi)型由用戶(hù)根據(jù)具體需要設(shè)定?;緮?shù)據(jù)類(lèi)型變量之間的值傳遞是簡(jiǎn)單的單向傳遞。JVM中傳遞各種類(lèi)型變量值的方法主要分為3種:①方法的參數(shù)為簡(jiǎn)單變量,進(jìn)行單向值傳遞;②方法的參數(shù)為數(shù)組變量,進(jìn)行地址傳遞;③方法的參數(shù)為對(duì)象變量,進(jìn)行地址傳遞。在如下代碼段中,fn1方法有3個(gè)重載的方法,參數(shù)分別為整型變量、數(shù)組變量和對(duì)象變量,試分析程序的運(yùn)行結(jié)果。

        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;? }

        }

        由運(yùn)行結(jié)果可知,在Java中,對(duì)于方法fn1,簡(jiǎn)單變量的值傳遞與其它語(yǔ)言中簡(jiǎn)單變量的值傳遞原理一致,都是單向傳遞,傳遞的是值本身,方法調(diào)用過(guò)程中不會(huì)改變?cè)兄?,并且JVM中所有的簡(jiǎn)單變量都保存在棧內(nèi)存中,與堆內(nèi)存沒(méi)有聯(lián)系,具體如圖7所示;對(duì)于方法fn2和fn3,當(dāng)數(shù)組或?qū)ο笞鳛榉椒ǖ膮?shù)時(shí),因?yàn)閭鬟f的是地址,地址改變時(shí),原來(lái)的值也跟隨改變,具體如圖8所示。

        4 內(nèi)部類(lèi)內(nèi)存模型

        類(lèi)的成員除變量和方法外,還可以有另一個(gè)成員內(nèi)部類(lèi)。內(nèi)部類(lèi)(也稱(chēng)Inner Class)指在一個(gè)類(lèi)中定義的另外一個(gè)類(lèi)。內(nèi)部類(lèi)和外部類(lèi)的定義方式一樣,其擁有自己獨(dú)立的屬性和方法,并將它們封裝在一個(gè)類(lèi)中。內(nèi)部類(lèi)擁有和方法一樣的訪(fǎng)問(wèn)權(quán)限,可以聲明為public、protected、default和private。內(nèi)部類(lèi)將邏輯上相關(guān)的一組類(lèi)組織起來(lái),由外部類(lèi)(OuterDemo Class)來(lái)控制其可見(jiàn)性[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();

        }

        }

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

        5 結(jié)語(yǔ)

        JVM定義了各種變量的內(nèi)存模型狀態(tài),每個(gè)變量都在自己的內(nèi)存空間中活動(dòng),同時(shí)又與其它內(nèi)存建立聯(lián)系。Java自動(dòng)管理?xiàng)?nèi)存和堆內(nèi)存,程序員不能直接設(shè)置棧內(nèi)存或堆內(nèi)存,棧內(nèi)存中放置基本類(lèi)型、局部變量和引用變量的值。引用變量存放在棧內(nèi)存中,對(duì)象內(nèi)容根據(jù)創(chuàng)建方式而定,由編譯器事先創(chuàng)建好并存放在常量池中,程序運(yùn)行時(shí)由new調(diào)用構(gòu)造方法創(chuàng)建的對(duì)象,存放在堆內(nèi)存中。 棧的優(yōu)點(diǎn)是數(shù)據(jù)共享、存取速度快;缺點(diǎn)是數(shù)據(jù)大小與生存期必須是確定的,缺少靈活性。

        堆內(nèi)存放置new調(diào)用構(gòu)造方法創(chuàng)建的對(duì)象。一旦在堆中產(chǎn)生數(shù)組或?qū)ο蠛螅梢栽跅V新暶饕粋€(gè)特殊變量,變量的值等于數(shù)組或?qū)ο笤诙褍?nèi)存中的首地址,棧里聲明的特殊變量則成了數(shù)組或?qū)ο蟮囊米兞?。其?shí),棧內(nèi)存中的變量指向堆內(nèi)存中的對(duì)象,可以被理解為JVM中的指針。由于堆內(nèi)存分配是在程序運(yùn)行時(shí)動(dòng)態(tài)進(jìn)行的,所以堆內(nèi)存的存取速度相對(duì)于棧內(nèi)存而言較慢。

        String類(lèi)表示一個(gè)字符串,在Java中所有的文字串,例如“abc”都是作為String類(lèi)的實(shí)例來(lái)實(shí)現(xiàn)的。String類(lèi)是Java中一個(gè)特殊的封裝類(lèi),它被聲明為final,用戶(hù)不能從String類(lèi)派生出其它類(lèi),一個(gè)String類(lèi)的對(duì)象是一個(gè)常量,創(chuàng)建之后值不能被改變。

        參考文獻(xiàn):

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

        [2] 張桂珠.JVM面向?qū)ο蟪绦蛟O(shè)計(jì)[M].第3版.北京:北京郵電大學(xué)出版社,2010.

        [3] 孫鑫.Java無(wú)難事[M].北京:電子工業(yè)出版社,2004.

        [4] 林樹(shù)澤.Java完全自學(xué)手冊(cè)[M].北京:機(jī)械工業(yè)出版社,2009.

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

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

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

        (責(zé)任編輯:杜能鋼)

        大屁股流白浆一区二区三区| 一区二区久久精品66国产精品| 在线观看视频亚洲一区二区三区 | 精品高朝久久久久9999| 九一九色国产| 狠狠躁夜夜躁人人爽天天| 国产偷拍盗摄一区二区| 国产色婷婷久久又粗又爽| 国产av麻豆mag剧集| 日韩精品国产自在久久现线拍| 日本高清中文字幕二区在线| 国产一区亚洲二区三区极品| 久久精品国产免费观看| 免费可以在线看A∨网站| 性感人妻av在线播放| 亚洲视频高清一区二区| 亚洲人成未满十八禁网站| 亚洲无码a∨在线视频| 亚洲五码av在线观看| 久久无码人妻丰满熟妇区毛片| 欧美性猛交内射兽交老熟妇| 人妻少妇精品视中文字幕国语| 久久老熟女一区二区三区福利| 国产精品久线在线观看| 国内精品大秀视频日韩精品| 精品亚洲视频免费观看网站| 亚洲国产精品无码一线岛国| a级毛片在线观看| 一区在线播放| 男人天堂亚洲天堂av| 首页 综合国产 亚洲 丝袜| 国产精品天堂avav在线| 一区二区三区一片黄理论片| a级国产乱理伦片| 麻豆精品久久久久久久99蜜桃| 亚洲区1区3区4区中文字幕码| 国产黄污网站在线观看| 国产成人亚洲精品无码mp4| 国产亚洲精品不卡在线| 亚洲成年国产一区二区| 无码av天堂一区二区三区 |