search
尋找貓咪~QQ 地點 桃園市桃園區 Taoyuan , Taoyuan

Java對於內存的需要知道的知識

內存大家都知道(當然不是硬碟啊)。與c、c++相比呢,Java在內存管理的方面一個優越之處就是我們不用顯式的去對對象進行內存的分配和內存的回收,可能有人會著迷於對內存使用分配的這種快感,但是隨著程序變大,對於內存的維護工作也就越來越大。Java的JVM的自動內存管理機制,凸顯出了強大的優越感。。。。

但反而是因為這樣的一個現狀,就弱化了我們在寫Java程序時遇到內存溢出等問題時的定位能力和解決問題的能力。就在這個時候一本書應運而生--- 《深入理解java虛擬機》 這本書也算是我旁邊落灰最嚴重的一本了,但寫程序就是這樣如果不沉到底,程序浮於表面那就只是單純的應用,不能變的熟練。

只有我們真正的了解了JVM如何管理內存后,才能遇見OutOfMemory錯誤時,快速的根據異常日誌信息定位和解決問題。

Java內存分配方式

咱們看看上面這張圖,顏色這麼鮮艷,這次一定能記住了!

  • 靜態 存儲區

    內存在程序編譯的時候就已經分配好了,這塊內存在程序的整個運行期間都存在。比如,static全局變數
  • 上創建

    在執行函數時,函數內局部變數的存儲單元都可以在棧上創建,函數執行結束時這些存儲單元自動被釋放。棧內存分匹配運算內置於處理器的指令集中、效率很高、但是分配的內存容量非常有限。
  • 上分配

    動態內存分配。在c和c++中運行程序時用 malloc 或 new申請任意大小的內存,我們需要自己決定自己在何時何地使用使用free和delete來釋放內存。

Java虛擬機內存模型是Java程序運行的基礎。虛擬機在執行Java程序的過程中會把他所管理的內存劃分為若干的不同的數據區域,ok,這裡加重

是分為不同的數據區域

,這些區域都有自己的用途以及創建和銷毀的時間。看一下下圖,

太好了,又畫了一個帶顏色的圖~那就說一說為什麼帶不同的顏色吧

  • 紫色,由所有線程共享的數據區
  • 線程隔離的數據區

程序計數器

寄存器裡面有一個叫指令寄存器,用來儲存現在正在被運行的指令。想象一下,在JVM中怎麼辦,程序寄存器就是這樣的功能。

程序技術器是一塊較小的內存空間,它可以看做是當前線程所執行的位元組碼的行號指示器。「位元組碼」就是Java程序被編譯之後的形態,JVM有位元組碼解釋器,這個解釋器要解釋程序的哪段,就由這個程序技術器來決定的。

Java虛擬機棧

Java虛擬機棧也是線程私有的,生命周期與線程相同,虛擬機棧描述的是Java方法執行的內存模型。每個方法在執行的同時會創建棧幀,保存

  • 局部變數表
  • 操作數棧
  • 動態鏈接
  • 方法出口

    每個方法從調用直到執行完成的過程,就對應整一個棧幀在虛擬機棧中入棧和出棧的過程。

    平時咱們在討論的時候總會提到「棧」和「堆」這兩種內存區域,那麼其中的棧,就是這裡所指的棧,更細一點說,就是虛擬機棧中局部變數的部分。

在換一個方面講解一下,虛擬機棧是用來被快速訪問的存儲區域,一般該區域位於通用RAM里,

這個RAM叫隨機存儲器,是與CPU直接交換數據的內存存儲器,也叫主存,可以隨時隨地的寫,而且速度快,通常作為操作系統或其他正在運行中的程序的臨時數據存儲媒介。

在虛擬機棧中,使用棧指針來訪問處理器。我們都學過棧這種數據結構,它是一種快速有效的 分配 存儲的方法,存儲速度僅次於寄存器,堆棧指針若向下移動,則分配新的內存,若向上移動則釋放那些內存。由於Java編譯器需要預先去生成相應的內存空間,所以,當我們嘗試創建程序的時候,Java編譯器必須知道被存儲在站內的所有數據的確切大小和聲明周期。一遍可以像上面描述的那樣去分配內存空間。

棧相對於堆的優勢就是比堆存取快,在棧中重要被用來存放一下基本類型的變數,例如int、short、long、byte、float、double、boolean、char,以及對象的引用(對象本身一般都存放在堆中)

StackOverFlow和OutOfMemoryError

Java虛擬機規範允許Java棧的大小是動態的或者是固定不變的。如果線程在計算過程中,請求的棧深度大於最大可用的棧深度,則在程序運行過程中會拋出StackOverFlow異常、如果Java棧可以動態擴展,而在擴展的過程中沒有足夠的內存空間支持棧的發展,在運行過程中會拋出OutOfMemoryError異常。

本地方法棧

本地方法棧與虛擬機棧所發揮的作用十分相似,區別就是虛擬機棧執行Java(位元組碼)的方法,本地棧是為虛擬機使用到Native方法。

Java堆

Java堆(Heap)是Java虛擬機所管理的內存中最大的一塊。堆是被所有線程共享的一塊內存區域,在虛擬機啟動時創建。次內存卻與的唯一目的就是存放對象示例,剛才在棧的部分也說了,棧中存的是對象的索引,而對象的實例存放在堆中。

在Java虛擬機規範中描述:所有的對象實例以及數組都要被在堆上分配內存。

GC(Garbage Collection)垃圾回收

由於堆和棧結構上的不同,所以其內存回收的機制也是不一樣的。

Java中對可以細分為:

再細分...

在內存的角度來看,線程共享的Java堆中可能劃分出多個線程私有的分配緩存區(Thread Local Allocation Buffer,TLAB)。Java堆可以處於物理上不連續的內存空間中,只要邏輯上是連續的即可,就像我們的磁碟空間一樣,在實現是,既可以實現成固定大小的,也可以是可擴展的,不過當前主流的虛擬機都是按照可擴展來實現的

-Xmx

-Xms

在堆中沒有內存完成實例分配,並且堆也無法在擴展時會拋出OutOfMemoryError異常。

方法區

方法區和Java堆是一樣的,是各個線程共享的內存區域,他用於儲存已被虛擬機載入的類的信息、常量、靜態變數、即時編譯器編譯后的代碼等數據。



熱門推薦

本文由 yidianzixun 提供 原文連結

寵物協尋 相信 終究能找到回家的路
寫了7763篇文章,獲得2次喜歡
留言回覆
回覆
精彩推薦