jvm 階段回顧

  內存基本分爲JAVA棧、本地方法棧、堆和方法區。

  首先棧存放的是基本類型變量,局部變量,和對象的引用,他在內存中是一塊連續的區域,有大小限制,是由系統自動分配的,因此它的讀寫速度比較快,而且會自動釋放掉爲該變量所分配的內存空間;還有一點就是他還存放線程調用方法時存儲局部變量表,操作,方法出口等與方法執行相關的信息。

  堆的話是存放對象和數組;在運行時動態分配內存(比如 new()),較慢,但靈活;是不連續的內存區域,在發出申請的時候,系統首先會遍歷一個存有空閒地址節點的鏈表,找到第一個滿足申請大小的節點,將他從鏈表刪除,並分配給申請者,如果空間剩餘,則將多出來的加入鏈表;由Java虛擬機的自動垃圾回收器來管理。分爲一個Eden區和兩個Survivor區。

  方法區主要存放靜態變量,常量,全局變量。他的大小不必是固定的,jvm可以根據應用的需要動態調整,同樣方法區也不必是連續的。方法區可以在堆(甚至是虛擬機自己的堆)中分配。jvm可以允許用戶和程序指定方法區的初始大小,最小和最大尺寸。因爲方法區是被所有線程共享的,所以必須考慮數據的線程安全。假如兩個線程都在試圖找一個類,在該類還沒有被加載的情況下,只應該有一個線程去加載,而另一個線程需要等待。

  本地方法棧則是爲執行Native方法服務,但這個在不同JVM內有不同的內部實現,比如在HotSpot JVM中Java虛擬機棧和本地方法棧被實現爲同一個棧區。

  對於收集方法來說一般有兩種,“複製”和“標記-清除-整理”。“複製”算法需要留有部分空間用於複製後的存儲,適用於朝生夕死的對象;“標記-清除-整理”適用於年老代,清除後形成邏輯上連續的區域,避免了內存碎片。

  對象被回收之前都要先被標記爲可回收的對象,一般有引用計數和可達性分析法。JAVA採用的則是可達性分析,從“GC Roots”開始組建一張張的關係網,不在關係網上的就會被清除。標記有兩次,因爲被標記後還可能會執行finalize()方法。“GC Roots”被記錄在OopMap中,能夠讓虛擬機快速的得到他們,不用遍歷整個堆來尋找“GC Roots”了。

  回收的時候需要暫停程序的所有線程,這個過程叫做STW,我們的程序需要優化的時候,縮短STW也是優化的一部分。

各種收集器都爲縮短STW的時間提供了不同的策略,並行的、串行的,作用於年輕代的,作用於年老代的,還有作用於整個堆的。各有各的優劣勢,需要搭配使用,不能隨意組合。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章