日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

Java内存之栈与堆

發(fā)布時間:2025/3/20 java 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java内存之栈与堆 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

?昨天中午,發(fā)了一篇equals和==區(qū)別的博文,晚上再看時有幾位大牛指出了其中的一些錯誤,很感謝他們的留言,一句簡簡單單的留言給了我對這些錯誤知識點改正的機會。或許這就是從事互聯(lián)網(wǎng)行業(yè)所提倡的互幫互助的精神吧,因為有分享,有交流,互聯(lián)網(wǎng)才會發(fā)展的如此迅猛。大牛提的一個觀點很好,好的東西可以拿出來分享,錯的東西卻可能帶給別人錯誤的理解,這一點我確實得向看了我寫了一些bug博客的人道個歉。

針對大牛所指出的錯誤,晚上翻出了資料,重新溫習(xí)了一遍。繼續(xù)總結(jié)一下:

一、在JVM中,內(nèi)存是如何被劃分的?

java把內(nèi)存分兩種:一種是棧內(nèi)存,另一種是堆內(nèi)存

1. 在函數(shù)中定義的基本類型變量和對象的引用變量都在函數(shù)的棧內(nèi)存中分配;(所以int的東西放在棧中)

2. 堆內(nèi)存用來存放由new創(chuàng)建的對象和數(shù)組以及對象的實例變量。

在函數(shù)(代碼塊)中聲明(這里并沒有實例化)一個變量時,java就在棧中為這個變量分配內(nèi)存空間,當(dāng)超過變量的作用域后,java會自動釋放掉為該變量所分配的內(nèi)存空間;在堆中分配的內(nèi)存由java虛擬機的自動垃圾回收器來管理

二、堆和棧的優(yōu)缺點比較
1. 堆的優(yōu)勢是可以動態(tài)分配內(nèi)存大小,生存期也不必事先告訴編譯器,因為它是在運行時動態(tài)分配內(nèi)存的;缺點就是要在運行時動態(tài)分配內(nèi)存,存取速度較慢。

2. 棧的優(yōu)勢是,存取速度比堆要快,僅次于直接位于CPU中的寄存器,棧數(shù)據(jù)可以共享;但缺點是,存在棧中的數(shù)據(jù)大小與生存期必須是確定的,缺乏靈活性。

三、new出來的對象存在內(nèi)存的什么地方?

在Java中,創(chuàng)建一個對象包括對象的聲明和對象的實例化兩部分。程序員需要通過關(guān)鍵字new為每個對象申請內(nèi)存空間(基本類型除外),所有的對象都在堆(heap)中分配空間。

舉例說明的一段代碼
  • public class NewTest {
  • double aaa;
  • double bbb;
  • public NewTest(double aa,double bb){
  • aaa = aa;
  • bbb = bb;
  • }
  • }
  • public class NewTest {double aaa;double bbb;public NewTest(double aa,double bb){aaa = aa;bbb = bb;} }

    上面的這段代碼,當(dāng)我們使用NewTest test = new NewTest()時,我們做如下分析:

    NewTest test : 聲明一個對象test時,將在棧內(nèi)存為對象的引用變量test分配內(nèi)存空間,但NewTest的值為空,稱test是一個空對象。空對象不能使用,因為它還沒有引用任何"實體"。

    test = new NewTest()時,在堆內(nèi)存中為類的成員變量aaa,bbb分配內(nèi)存,并將其初始化為各數(shù)據(jù)類型的默認(rèn)值;接著進行顯式初始化(類定義時的初始化值);最后調(diào)用構(gòu)造方法,為成員變量賦值,返回堆內(nèi)存中對象的引用(相當(dāng)于首地址)給引用變量test,以后就可以通過test來引用堆內(nèi)存中的對象了。

    ?

    創(chuàng)建兩個不同對象代碼
  • NewTest test1 = new NewTest();
  • NewTest test2 = new NewTest();
  • NewTest test1 = new NewTest(); NewTest test2 = new NewTest();

    在使用同一個類創(chuàng)建兩個不同的對象的時候,這些對象實例將在堆中被分配到不同的內(nèi)存空間,改變其中一個對象的狀態(tài)不會影響其他對象的狀態(tài)。

    四、Java基本類型在內(nèi)存中的存儲

    這里重點討論一下八種基本類型(int, short, long, byte, float, double, boolean, char)在內(nèi)存中時如何存放的。我們所指的八種基本類型定義的變量,是指形式如 int a=3、char aa ='a'類型的,即不通過new的。這里的aa時指向char類型的一個引用,指向'a'這個字面值。這些字面值的數(shù)據(jù),由于大小可知,生存期可知(這些字面值定義在某個程序塊里面,程序塊退出后,字段值就消失了),出于追求速度的原因,就存在于中。

    另外,棧有一個很重要的特殊性,就是存在棧中的數(shù)據(jù)可以共享。

    比如:我們同時定義:

    long a =3;

    long b =3;

    編譯器處理的過程是:

    1. 編譯器先處理long a = 3;首先它會在棧中創(chuàng)建一個變量為a的引用,然后查找有沒有字面值為3的地址,沒找到,就開辟一個存放3這個字面值的地址,然后將a指向3的地址。

    2. 接著處理long b = 3;在創(chuàng)建完b這個引用變量后,由于在棧中已經(jīng)有3這個字面值,便將b直接指向3的地址。這樣,就出現(xiàn)了a與b同時均指向3的情況。

    定義完a與b的值后,如果再令a = 4,這時,b不會等于4,還是等于3。在編譯器內(nèi)部,遇到時,它就會重新搜索棧中是否有4的字面值,如果沒有,重新開辟地址存放4的值;如果已經(jīng)有了,則直接將a指向這個地址。因此a值的改變不會影響到b的值。

    五、基本類型對應(yīng)的包裝類

    基本類型都有對應(yīng)的包裝類:如int對應(yīng)Integer類,double對應(yīng)Double類等,基本類型的定義都是直接在棧中,如果用包裝類來創(chuàng)建對象,就和普通對象一樣了。例如:

    int a=0;a直接存儲在棧中。

    Integer b= new Integer(5);b對象數(shù)據(jù)(這里指的是5)存儲在堆中,b的引用存儲在棧中,通過棧中的引用來操作對象。

    六、String在內(nèi)存中的存放

    String是一個特殊的包裝類數(shù)據(jù),可以用用以下兩種方式創(chuàng)建:

    String str = new String("abc");第一種創(chuàng)建方式,和普通對象的的創(chuàng)建過程一樣;

    String str = "abc"; 第二種創(chuàng)建方式,類似于基本數(shù)據(jù)類型的創(chuàng)建,變量名和數(shù)據(jù)存放在棧空間中

    七、數(shù)組在內(nèi)存中的存放

    int x[] 或者int []x 時,在內(nèi)存棧空間中創(chuàng)建一個數(shù)組引用,通過該數(shù)組名來引用數(shù)組。

    x = new int[5] 將在堆內(nèi)存中分配5個保存int型數(shù)據(jù)的空間,堆內(nèi)存的首地址放到棧內(nèi)存中,每個數(shù)組元素被初始化為0.

    八、static變量在內(nèi)存中的存放

    用static的修飾的變量和方法,實際上是指定了這些變量和方法在內(nèi)存中的"固定位置"-static storage,可以理解為所有實例對象共有的內(nèi)存空間。static變量有點類似于C中的全局變量的概念;靜態(tài)表示的是內(nèi)存的共享,就是它的每一個實例都指向同一個內(nèi)存地址。把static拿來,就是告訴JVM它是靜態(tài)的,它的引用(含間接引用)都是指向同一個位置,在那個地方,你把它改了,它就不會變成原樣,你把它清理了,它就不會回來了。

    那靜態(tài)變量與方法是在什么時候初始化的呢?

    對于兩種不同的類屬性,static屬性與instance屬性,初始化的時機是不同的。instance屬性在創(chuàng)建實例的時候初始化,static屬性在類加載,也就是第一次用到這個類的時候初始化,對于后來的實例的創(chuàng)建,不再進行初始化。

    轉(zhuǎn)載于:https://blog.51cto.com/shuaigee/1131734

    總結(jié)

    以上是生活随笔為你收集整理的Java内存之栈与堆的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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