1. 程式人生 > >Java中的資料儲存(堆及堆疊)

Java中的資料儲存(堆及堆疊)

轉自:http://www.iteye.com/topic/634530
1.暫存器:最快的儲存區, 由編譯器根據需求進行分配,我們在程式中無法控制.
2. 棧:存放基本型別的變數資料和物件的引用,但物件本身不存放在棧中,而是存放在堆(new 出來的物件)或者常量池中(物件可能在常量池裡)(字串常量物件存放在常量池中。)
3. 堆:存放所有new出來的物件。
4. 靜態域:存放靜態成員(static定義的)
5. 常量池:存放字串常量和基本型別常量(public static final)。有時,在嵌入式系統中,常量本身會和其他部分分割離開(由於版權等其他原因),所以在這種情況下,可以選擇將其放在ROM中 。
6. 非RAM儲存:硬碟等永久儲存空間

這裡我們主要關心棧,堆和常量池,對於棧和常量池中的物件可以共享,對於堆中的物件不可以共享。棧中的資料大小和生命週期是可以確定的

,當沒有引用指向資料時,這個資料就會消失。堆中的物件的由垃圾回收器負責回收,因此大小和生命週期不需要確定,具有很大的靈活性。
對於字串:其物件的引用都是儲存在棧中的,如果是編譯期已經建立好(直接用雙引號定義的)的就儲存在常量池中,如果是執行期(new出來的)才能確定的就儲存在堆中。對於equals相等的字串,在常量池中永遠只有一份,在堆中有多份
如以下程式碼:

Java程式碼  收藏程式碼
  1. String s1 = "china";  
  2. String s2 = "china";  
  3. String s3 = "china";  
  4. String ss1 = new String("china");  
  5. String ss2 = new String("china");  
  6. String ss3 = new String("china");  



 

這裡解釋一下黃色這3個箭頭,對於通過new產生一個字串(假設為”china”)時,會先去常量池中查詢是否已經有了”china”物件,如果沒有則在常量池中建立一個此字串物件,然後堆中再建立一個常量池中此”china”物件的拷貝物件。這也就是有道面試題:String s = new String(“xyz”);產生幾個物件?一個或兩個,如果常量池中原來沒有”xyz”,就是兩個。

對於基礎型別的變數和常量:變數和引用儲存在棧中,常量儲存在常量池中。
如以下程式碼:

Java程式碼  收藏程式碼
  1. int i1 = 9;  
  2. int i2 = 9;  
  3. int i3 = 9;   
  4. public static final int INT1 = 9;  
  5. public static final int INT2 = 9;  
  6. public static final int INT3 = 9;  




對於成員變數和區域性變數:成員變數就是方法外部,類的內部定義的變數;區域性變數就是方法或語句塊內部定義的變數。區域性變數必須初始化。
形式引數是區域性變數,區域性變數的資料存在於棧記憶體中。棧記憶體中的區域性變數隨著方法的消失而消失。
成員變數儲存在堆中的物件裡面,由垃圾回收器負責回收。
注意:棧裡只有一個9 ,i1,i2,i3 都指向9 。如果 令 i2=7會在棧裡生成7 再令i2 指向7。
如以下程式碼:

Java程式碼  收藏程式碼
  1. class BirthDate {  
  2.     private int day;  
  3.     private int month;  
  4.     private int year;      
  5.     public BirthDate(int d, int m, int y) {  
  6.         day = d;   
  7.         month = m;   
  8.         year = y;  
  9.     }  
  10.     省略get,set方法………  
  11. }  
  12. public class Test{  
  13.     public static void main(String args[]){  
  14. int date = 9;  
  15.         Test test = new Test();        
  16.            test.change(date);   
  17.         BirthDate d1= new BirthDate(7,7,1970);         
  18.     }    
  19.     public void change1(int i){  
  20.         i = 1234;  
  21.     }  

}


對於以上這段程式碼,date為區域性變數,i,d,m,y都是形參為區域性變數,day,month,year為成員變數。下面分析一下程式碼執行時候的變化:
1. main方法開始執行:int date = 9;
date區域性變數,基礎型別,引用和值都存在棧中
2. Test test = new Test();
test為物件引用,存在棧中,物件(new Test())存在堆中。
3. test.change(date);
i為區域性變數,引用和值存在棧中。當方法change執行完成後,i就會從棧中消失。
4. BirthDate d1= new BirthDate(7,7,1970);  
d1為物件引用,存在棧中,物件(new BirthDate())存在堆中,其中d,m,y為區域性變數儲存在棧中,且它們的型別為基礎型別,因此它們的資料也儲存在棧中。day,month,year為成員變數,它們儲存在堆中(new BirthDate()裡面)。當BirthDate構造方法執行完之後,d,m,y將從棧中消失。
5.main方法執行完之後,date變數,test,d1引用將從棧中消失,new Test(),new BirthDate()將等待垃圾回收
------------------------------------------------------------------------------------------------------------------------------
JVM 中的堆疊
JVM是基於堆疊的虛擬機器.JVM為每個新建立的執行緒都分配一個堆疊.也就是說,對於一個Java程式來說,它的執行就是通過對堆疊的操作來完成的。堆疊以幀為單位儲存執行緒的狀態。JVM對堆疊只進行兩種操作:以幀為單位的壓棧和出棧操作。 
  我們知道,某個執行緒正在執行的方法稱為此執行緒的當前方法.我們可能不知道,當前方法使用的幀稱為當前幀。當執行緒啟用一個Java方法,JVM就會線上程的 Java堆疊裡新壓入一個幀。這個幀自然成為了當前幀.在此方法執行期間,這個幀將用來儲存引數,區域性變數,中間計算過程和其他資料.這個幀在這裡和編譯原理中的活動紀錄的概念是差不多的. 
  從Java的這種分配機制來看,堆疊又可以這樣理解:堆疊(Stack)是作業系統在建立某個程序時或者執行緒(在支援多執行緒的作業系統中是執行緒)為這個執行緒建立的儲存區域,該區域具有先進後出的特性。 
  每一個Java應用都唯一對應一個JVM例項,每一個例項唯一對應一個堆。應用程式在執行中所建立的所有類例項或陣列都放在這個堆中,並由應用所有的執行緒共享.跟C/C++不同,Java中分配堆記憶體是自動初始化的。Java中所有物件的儲存空間都是在堆中分配的,但是這個物件的引用卻是在堆疊中分配,也就是說在建立一個物件時從兩個地方都分配記憶體,在堆中分配的記憶體實際建立這個物件,而在堆疊中分配的記憶體只是一個指向這個堆物件的指標(引用)而已。

JAVA 堆疊
棧與堆都是Java用來在Ram中存放資料的地方。與C++不同,Java自動管理棧和堆,程式設計師不能直接地設定棧或堆。
  Java的堆是一個執行時資料區,類的(物件從中分配空間。這些物件通過new、newarray、anewarray和multianewarray等指令建立,它們不需要程式程式碼來顯式的釋放。堆是由垃圾回收來負責的,堆的優勢是可以動態地分配記憶體大小,生存期也不必事先告訴編譯器,因為它是在執行時動態分配記憶體的,Java的垃圾收集器會自動收走這些不再使用的資料。但缺點是,由於要在執行時動態分配記憶體,存取速度較慢。 
  棧的優勢是,存取速度比堆要快,僅次於暫存器,棧資料可以共享。但缺點是,存在棧中的資料大小與生存期必須是確定的,缺乏靈活性。棧中主要存放一些基本型別的變數(,int, short, long, byte, float, double, boolean, char)和物件控制代碼。 
  棧有一個很重要的特殊性,就是存在棧中的資料可以共享。假設我們同時定義: 
  int a = 3; 
  int b = 3; 
  編譯器先處理int a = 3;首先它會在棧中建立一個變數為a的引用,然後查詢棧中是否有3這個值,如果沒找到,就將3存放進來,然後將a指向3。接著處理int b = 3;在建立完b的引用變數後,因為在棧中已經有3這個值,便將b直接指向3。這樣,就出現了a與b同時均指向3的情況。這時,如果再令a=4;那麼編譯器會重新搜尋棧中是否有4值,如果沒有,則將4存放進來,並令a指向4;如果已經有了,則直接將a指向這個地址。因此a值的改變不會影響到b的值。要注意這種資料的共享與兩個物件的引用同時指向一個物件的這種共享是不同的,因為這種情況a的修改並不會影響到b, 它是由編譯器完成的,它有利於節省空間。而一個物件引用變數修改了這個物件的內部狀態,會影響到另一個物件引用變數 
----------------------------------------------------------------------------------------------
另外還有一個疑問:
int [] arr={1,2,3,4}
即沒有用new 顯示生成的原始型別陣列是存放在哪的
是存放在堆還是棧裡。
在c++ 裡肯定是在棧裡(C++ 在堆裡生成的一定要手動delete 掉自己回收的,而int a[]={1,3}我們不需手動回收)

相關推薦

Java資料儲存堆疊

轉自:http://www.iteye.com/topic/634530 1.暫存器:最快的儲存區, 由編譯器根據需求進行分配,我們在程式中無法控制. 2. 棧:存放基本型別的變數資料和物件的引用,但物件本身不存放在棧中,而是存放在堆(new 出來的物件)或者常量池中(物

Java帶包建立引用的類的編譯

Java中帶包(建立及引用)的類的編譯 Java中帶包(建立及引用)的類的編譯與除錯 java源程式的編譯大家都知道,也就是cmd中到原始檔所在目錄下javac **.java即可,當程式中有包宣告還能簡簡單單的直接javac **.java嗎?答案當然是no,下面舉個簡單的例子證明一下直接

Java資料儲存、棧、常量池)

原文轉自http://bbs.itheima.com/thread-9597-1-1.html 1.暫存器:最快的儲存區, 由編譯器根據需求進行分配,我們在程式中無法控制。 2.棧:存放基本型別的變數資料和物件的引用,但物件本身不存放在棧中,而是存放在堆(new 出來的物件)

java資料型別在與棧儲存

1.基本資料型別 eg:int i=1; 基本資料型別都存在棧中,它並沒有建立物件,只是將值放入變數的引用中。 2.引用型別         2.1  String a="abc"; //實際上a是引用變數,"abc"是物件(其實也算不上物

java方法總結每周更新

實例 參數 創建 方法 get ack bject 子類 generate 1、URLEncoder.encode(username,"utf-8")將“utf-8”編碼的username先解碼,然後再采用URL編碼 2、URLDecoder.decode(autoLogi

3java基本資料型別常量、轉換

java基本資料型別 變數的作用:申請記憶體來儲存值。(申請什麼型別的變數就只能儲存什麼型別的變數) java兩大資料型別: 內建資料型別 引用資料型別 內建資料型別 共8種 6種數字型別(四個整型、兩個浮點型) 1

jQuery之ajax資料互動語法示例

一、jajx基礎語法  1.1寫法 $.ajax({   url:'地址',   data:{     引數:xxx,       引數:xxx   },   type:'POST/GET',   success:function(str){ //成功回撥函式

JAVAMD5加密MD5工具類

工具類如下:import java.security.MessageDigest; /** * @Author:Starry * @Description: * @Date:Created in 9

Java基礎3Java的日期Date與Calendar

一、關於Date private static void dateTest(){ //定義時區,可以避免虛擬機器時間與系統時間不一致的問題 // TimeZone.setDefault(TimeZ

Java的集合List和Set

Java容器類主要是為了“儲存物件”,並將其劃分為兩個不同的概念:Collection,獨立元素的集合,這些元素都服從一條或多條規則,如List必須按照插入順序儲存元素,Set不能有重複元素,Queue按照排隊規則來確定物件的順序。Map形成一組“鍵值對”物件,允許你使用鍵

聊聊java的繼承附面試題

首先了解下為什麼要有繼承 舉個例子,我們要定義幾個類,學生類,老師類,清潔工類,在他們裡面都要定義一個吃飯的方法,那麼,每個類裡面都定義是不是有些麻煩,於是出現了繼承,想想,學生老師清潔工都是人,這個時候我們可以定義一個人類,裡面定義一個吃飯的方法,然後這幾個類再繼承人類,

Solr全文搜尋伺服器的搭建以及在Java的使用solr單機版

直接步入正題。。。。。。Solr的搭建環境:JDK:1.8.0_161Tomcat:7.0.57OS:CentOS 7Solr服務搭建:第一步:將solr的壓縮包上傳至Linux系統,下載地址:http://www.apache.org/dyn/closer.lua/luce

Java的記憶體機制和棧簡單理解

偶然看到一道面試題,Java在例項化一個類的時候,資料在堆和棧中是如何存放的? public class A{ public int i=1; public static A a1

Java時間格式化獲取指定時間

Java中時間格式化(獲取指定時間,七天前) 1、通過獲取當前系統時間,格式化後轉為“yyyy-MM-dd HH:mm:ss”格式並輸出; 2、可獲取指定時間,如七天前,一年前等,使用者通過時間段查

JAVA讀取檔案二進位制,字元內容的方法總結

publicclass ReadFromFile {     /**      * 以位元組為單位讀取檔案,常用於讀二進位制檔案,如圖片、聲音、影像等檔案。      */publicstaticvoid readFileByBytes(String fileName) {         File file

java型別轉換String float int

這幾種型別裝換,一般都會用到parseInt()、parseFloat() 、valueof()方法,但是這是有區別的。 看看他們的返回型別不同 static int parseInt(String s) 將字串引數作為有符號的十進

重要!java資料的5種儲存位置(與棧) 成員變數區域性變數記憶體分配

來源: java中資料的5種儲存位置(堆與棧) http://blog.csdn.net/ghost_programmer/article/details/40891735 http://www.cnblogs.com/newveg/p/6591435.html

java資料的5種儲存位置(與棧)

任何語言所編寫的程式,其中的各型別的資料都需要一個儲存位置,Java中資料的儲存位置分為以下5種: 1.暫存器 最快的儲存區,位於處理器內部,但是數量極其有限。所以暫存器根據需求進行自動分配,無法直接人為控制。 2.棧記憶體 位於RAM當中,通過堆疊指標可以從處理器獲得直接支援。堆疊指標向下

IOS iPhone 開發的檔案讀寫資料儲存

 資料的儲存無疑是軟體開發中的重要課題。本文給初學者介紹下iphone開發中常見的檔案讀寫,當然,我也是初學者~ iOS的檔案儲存採用的是“沙箱機制”,也就是應用程式只能訪問自己的檔案目錄,每個應用程式的資料是獨立的,就像一個一個的沙箱一樣。這種管理方法比windows和原

python爬取大眾點評網商家資訊以及評價,並將資料儲存到excel表原始碼註釋

import requests from bs4 import BeautifulSoup import traceback # 異常處理 import xlwt # 寫入xls表 # Cookie記錄登入資訊,session請求 def get_content(url,he