1. 程式人生 > >C++和JAVA在記憶體管理上的特點

C++和JAVA在記憶體管理上的特點

Java的記憶體管理實質上就是JVM的記憶體管理
  JVM的記憶體分為兩部分:stack和heap
  Stack(棧)是指JVM的記憶體指令區。Java基本資料型別,Java指令程式碼,常量都存在stack中。
  heap(堆)是JVM的記憶體資料區。heap專門用來儲存物件的例項,實際上也只是儲存物件例項的屬性值,屬性的型別和物件本身的型別標記等,並不儲存物件的方法(方法是指令,儲存在Stack中),物件例項在heap中分配好後需要在Stack中儲存1個4位元組的heap記憶體地址,用來定位該物件在heap中的位置,以便找到該物件例項。
  Stack不存在記憶體管理問題,系統自動管理,heap

中的物件由GC負責垃圾回收。
  GC垃圾收集的規程:GC程序定期掃描heap,他根據stack中儲存的4位元組物件地址掃描heap,定位heap中的這些物件,進行一些優化,並且假設heap中的沒有掃描到區域都是空閒的,統統refresh(實際上是把stack中丟失物件地址的無用物件清除了)。這就是垃圾回收的過程。
  關於物件
  1、方法本身是指令的操作碼部分,報存在stack中;
  2、方法內部變數作為指令的運算元部分,跟在指令的操作碼之後,儲存在stack中(實際上是簡單型別儲存在stack中,物件例項在stack中儲存地址,在heap中儲存值)
  上述的指令運算元和指令操作碼構成完整的Java指令。
  3、物件例項包括屬性值作為資料,儲存在heap中。
  關於靜態方法和靜態屬性
  當一個ClassLoader load進入JVM後,方法指令報存在stack中,此時heap區沒有資料,然後程式計數器開始執行指令,如果是一個靜態方法,直接依次執行指令程式碼,當然此時指令程式碼無法訪問heap資料區;如果是非靜態方法,由於隱含引數沒有值,會報錯。因此在非靜態方法執行之前,要先new物件,在heap中分配資料,並把stack中的地址指標交給非靜態方法,這樣程式計數器一次執行指令,而指令程式碼就能夠訪問到heap資料區。
  由於上述的原因,靜態屬性是 儲存在stack中的(基本型別報存在stack,物件型別地址儲存在stack中,值報存在heap中),並因此具有全域性屬性。
  補充:字串常量在stack分配,this在heap中分配,陣列想物件一樣既在stack中分配地址放陣列名稱,又在heap中分配陣列實際大小的空間。
  下面再說C/C++記憶體管理
  在C++中,記憶體分為5個區,他們分別是堆、棧、自由儲存區、全域性/靜態儲存區和常量儲存區。
  棧:編譯器自動管理,裡面的變數是區域性變數、函式引數等(可以用alloca函式分配)
  堆:由new分配的記憶體塊,用delete釋放
  自由儲存區:由malloc分配,用free釋放和堆很相似
  全域性/靜態儲存區:全域性變數和靜態變數
  常量儲存區:常量