Java記憶體分析,java記憶體
前言
看代碼,或許我們只能瞭解程式執行的先後順序,通過記憶體分析,我們可以瞭解程式執行過程中的記憶體配置情況。前者是在時間維度上進行分析,後者是在空間維度上進行分析。本文目的就是將具體代碼與其執行過程中的記憶體配置情況對應起來,使大家對這塊內容有個清晰的認識。
概述
根據,我們首先來介紹一下整個程式執行過程。主要分為三步:
補充:
程式檔案本身放在硬碟上,副檔名可以是.exe或者是.class等。
記憶體管理即本文主要介紹的問題。記憶體管理過程中會將記憶體分為四塊地區:堆區(Heap),棧區(Stack),資料區(Data Segment),代碼區(Code Segment)。
總體而言,要記住以下四點:
1.new出來的東西放到堆區;
2.局部變數放到棧區;
3.靜態變數和字串常量放到資料區;
4.代碼放到代碼區。
以上四點是根本準則,下面的就是具體要強調的細節了。
具體情況類和對象
程式執行過程中,定義的類的代碼會載入到記憶體中的代碼區;
對象在執行個體化的過程中(new)產生。
如所示,類C的代碼會載入到代碼區;在執行main方法時,c1和c2屬於局部變數,會在棧區分配兩塊空間;new C()的過程中,會在堆區分配空間,這塊空間屬於某個對象,在該對象的控空間中,包括了成員變數的空間。
備忘:數組也屬於參考型別,所以它的記憶體配置狀況同對象。
方法
方法執行時,首先為方法的形參分配空間,形參等同於局部變數,所以在棧記憶體配置空間。接著,採用值傳遞的方式,實參把值複製給形參。方法有傳回值時,傳回值也會在棧中有塊臨時記憶體,沒有名字。
方法執行完畢之後,為方法執行分配的局部變數及傳回值的臨時的空間消失。
繼承
如所示,如果“Class Student extends Person”,則在new Student ( )時,堆中分配的屬於該對象的空間中,會同時有父物件的空間。即子類對象比父類對象大,子類對象擁有父類對象。同時具有this和super引用,分別指向整個對象和其中的父物件。
靜態變數和字串常量
以下是一段具有靜態成員變數和字串常量的代碼:
public class Cat { private static int sid = 0;//靜態成員變數 private String name; //成員變數 int id; Cat(String name) { this.name = name; id = sid++; } public void info(){ System.out.println ("My name is "+name+" No."+id); } public static void main(String arg[]){ Cat mimi = new Cat("mimi"); //"mimi"為字串常量 Cat pipi = new Cat("pipi"); mimi.info(); pipi.info(); }}
如所示靜態變數只有一份,存在於資料區;字串常量也存在於資料區。
多態
多態存在有三個條件:繼承,重寫,父類引用指向子類對象。記憶體配置情況同繼承時的記憶體配置情況。只是當向上轉型時,只能訪問父類的成員變數,而在執行重寫方法時,會根據實際綁定的子類對象,執行子類對象的方法。
如:Animal a= new Dog();該對象只能訪問name屬性,不能訪問子類對象的furColor屬性。
動態決定執行哪段方法代碼。Animal和Cat都有enjoy方法,當Animal a= new Cat(); a.enjoy();在執行過程中,會決定執行Cat中的enjoy方法的代碼。
總結
瞭解記憶體配置過程,就是在瞭解代碼背後的故事,以上是基礎的一些內容,如果要和之前學過的內容聯絡起來,我想這些知識或許對理解C++中的指標,建構函式,傳值調用,傳址調用等有協助。如果展望一下這些基礎知識的潛在價值,這或許對我今後最佳化自己的代碼,減少記憶體消耗有協助吧!
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。