自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

深入理解Java的棧與堆及JVM之內存分配與圖解

存儲 存儲軟件
在堆中分配的內存,由Java虛擬機的自動垃圾回收器來管理。在堆中產(chǎn)生了一個數(shù)組或對象后,還可以在棧中定義一個特殊的變量,讓棧中這個變量的取值等于數(shù)組或對象在堆內存中的首地址,棧中的這個變量就成了數(shù)組或對象的引用變量。

 

Java把內存劃分成兩種:一種是棧內存,一種是堆內存。

 

1.棧(stack)與堆(heap)都是Java用來在Ram中存放數(shù)據(jù)的地方。與C++不同,Java自動管理棧和堆,程序員不能直接地設置?;蚨?。

2. 棧的優(yōu)勢是,存取速度比堆要快,僅次于直接位于CPU中的寄存器。但缺點是,存在棧中的數(shù)據(jù)大小與生存期必須是確定的,缺乏靈活性。另外,棧數(shù)據(jù)可以共享。堆的優(yōu)勢是可以動態(tài)地分配內存大小,生存期也不必事先告訴編譯器,Java的垃圾收集器會自動收走這些不再使用的數(shù)據(jù)。但缺點是,由于要在運行時動態(tài)分配內存,存取速度較慢。

3. Java中的數(shù)據(jù)類型有兩種。

一種是基本類型(primitive types), 共有8種,即int, short, long, byte, float, double, boolean, char(注意,并沒有string的基本類型)。這種類型的定義是通過諸如int a = 3; long b = 255L;的形式來定義的,稱為自動變量。值得注意的是,自動變量存的是字面值,不是類的實例,即不是類的引用,這里并沒有類的存在。如int a = 3; 這里的a是一個指向int類型的引用,指向3這個字面值。這些字面值的數(shù)據(jù),由于大小可知,生存期可知(這些字面值固定定義在某個程序塊里面,程序塊退出后,字段值就消失了),出于追求速度的原因,就存在于棧中。

另外,棧有一個很重要的特殊性,就是存在棧中的數(shù)據(jù)可以共享。假設我們同時定義:int a = 3; int b = 3; 編譯器先處理int a = 3;首先它會在棧中創(chuàng)建一個變量為a的引用,然后查找有沒有字面值為3的地址,沒找到,就開辟一個存放3這個字面值的地址,然后將a指向3的地址。接著處理int b = 3;在創(chuàng)建完b的引用變量后,由于在棧中已經(jīng)有3這個字面值,便將b直接指向3的地址 。這樣,就出現(xiàn)了a與b同時均指向3的情況。 特別注意的是,這種字面值的引用與類對象的引用不同。假定兩個類對象的引用同時指向一個對象,如果一個對象引用變量修改了這個對象的內部狀態(tài),那么另一個對象引用變量也即刻反映出這個變化。相反,通過字面值的引用來修改其值,不會導致另一個指向此字面值的引用的值也跟著改變的情況。如上例,我們定義完a與b的值后,再令a=4;那么,b不會等于4,還是等于3。在編譯器內部,遇到a=4;時,它就會重新搜索棧中是否有4的字面值,如果沒有,重新開辟地址存放4的值;如果已經(jīng)有了,則直接將a指向這個地址。因此a值的改變不會影響到b的值。

另一種是包裝類數(shù)據(jù),如Integer, String, Double等將相應的基本數(shù)據(jù)類型包裝起來的類。這些類數(shù)據(jù)全部存在于堆中,Java用new()語句來顯示地告訴編譯器,在運行時才根據(jù)需要動態(tài)創(chuàng)建,因此比較靈活,但缺點是要占用更多的時間。

通過上面的基本講解,我們通過幾個問題來進一步深入理解,如圖所示:

 

在函數(shù)中定義的一些基本類型的變量和對象的引用變量都在函數(shù)的棧內存中分配。當在一段代碼塊定義一個變量時,Java就在棧中為這個變量分配內存空間,當超過變量的作用域后,Java會自動釋放掉為該變量所分配的內存空間,該內存空間可以立即被另作他用。

堆內存用來存放由new創(chuàng)建的對象和數(shù)組。在堆中分配的內存,由Java虛擬機的自動垃圾回收器來管理。在堆中產(chǎn)生了一個數(shù)組或對象后,還可以在棧中定義一個特殊的變量,讓棧中這個變量的取值等于數(shù)組或對象在堆內存中的首地址,棧中的這個變量就成了數(shù)組或對象的引用變量。引用變量就相當于是為數(shù)組或對象起的一個名稱,以后就可以在程序中使用棧中的引用變量來訪問堆中的數(shù)組或對象。

String是一個特殊的包裝類數(shù)據(jù)。可以用: String str = new String("abc");String str = "abc";兩種的形式來創(chuàng)建,第一種是用new()來新建對象的,它會在存放于堆中。每調用一次就會創(chuàng)建一個新的對象。而第二種是先在棧中創(chuàng)建一個對String類的對象引用變量str,然后查找棧中有沒有存放"abc",如果沒有,則將"abc"存放進棧,并令str指向”abc”,如果已經(jīng)有”abc” 則直接令str指向“abc”。比較類里面的數(shù)值是否相等時,用equals()方法;當測試兩個包裝類的引用是否指向同一個對象時,用==,下面用例子說明上面的理論。

  1. String str1 = "abc"
  2. String str2 = "abc"
  3. System.out.println(str1==str2); //true 

可以看出str1和str2是指向同一個對象的。

  1. String str1 =new String ("abc"); 
  2. String str2 =new String ("abc"); 
  3. System.out.println(str1==str2); // false 

用new的方式是生成不同的對象,每new一次生成一個。

因此用第二種方式創(chuàng)建多個”abc”字符串,在內存中其實只存在一個對象而已. 這種寫法有利與節(jié)省內存空間. 同時它可以在一定程度上提高程序的運行速度,因為JVM會自動根據(jù)棧中數(shù)據(jù)的實際情況來決定是否有必要創(chuàng)建新對象。而對于String str = new String("abc");的代碼,則一概在堆中創(chuàng)建新對象,而不管其字符串值是否相等,是否有必要創(chuàng)建新對象,從而加重了程序的負擔。

另一方面, 要注意: 我們在使用諸如String str = "abc";的格式定義類時,總是想當然地認為,創(chuàng)建了String類的對象str。(不一定,因為如果事先沒有,那么就會創(chuàng)建,這就是創(chuàng)建對象了,如果原來就有,那就指向那個原來的對象就可以了)!對象可能并沒有被創(chuàng)建!而可能只是指向一個先前已經(jīng)創(chuàng)建的對象。只有通過new()方法才能保證每次都創(chuàng)建一個新的對象。由于String類的immutable性質,當String變量需要經(jīng)常變換其值時,應該考慮使用StringBuffer類,以提高程序效率。

最后我們通過掌握來堆與棧的基本知識后,來簡單的了解一下JVM的內存分配,我這里就用寫好的代碼截圖展示出來:

 

運行的結果是:com.jvm1.Person@1bc4459 與 20 。

圖解:

 

當實例化 Person person=new Person(); 方法區(qū)存放了 方法的信息 public int getAge,public void setAge 。

堆存放了 new Person() 對象。

棧存放了 person 對象的引用地址 1bc4459 并且指向堆中的 new Person() 對象 和 其 成員變量 private int age;

當調用 person.setAge(20); 方法時 棧中存放 age=20 并且賦值給 對象成員變量 this.age=age=20。

責任編輯:武曉燕 來源: 今日頭條
相關推薦

2015-12-28 11:41:57

JVM內存區(qū)域內存溢出

2009-06-03 15:52:34

堆內存棧內存Java內存分配

2024-04-30 08:38:31

C++

2010-09-27 08:38:49

JVM堆JVM棧

2023-11-05 12:05:35

JVM內存

2020-11-04 15:35:13

Golang內存程序員

2021-11-26 00:00:48

JVM內存區(qū)域

2019-02-26 14:33:22

JVM內存虛擬機

2010-03-12 08:55:06

Java內省反射

2024-08-28 15:13:54

2010-09-27 11:24:50

JREJVM

2011-12-20 10:43:21

Java

2023-12-31 12:56:02

C++內存編程

2021-05-19 07:56:26

Linux內核搶占

2021-09-08 17:42:45

JVM內存模型

2023-10-27 07:47:58

Java語言順序性

2023-09-19 22:47:39

Java內存

2022-07-06 08:05:52

Java對象JVM

2022-12-28 09:07:41

2024-03-29 11:42:21

Java虛擬機
點贊
收藏

51CTO技術棧公眾號