1. 程式人生 > >第二章 JVM記憶體分配

第二章 JVM記憶體分配

注意:本篇部落格,主要參考自以下四本書

《分散式Java應用:基礎與實踐》

《深入理解Java虛擬機器(第二版)》

《突破程式設計師基本功的16課》

《實戰java虛擬機器》

說明:關於JVM記憶體結構,檢視《第一章 JVM記憶體結構》,下面所講的JVM記憶體分配主要是指在Hotspot JVM下新建物件在堆記憶體中分配的情況。

1、建立一個真正物件的基本過程

五步:

  • 類載入機制檢查
    • JVM首先檢查一個new指令的引數是否能在常量池中定位到一個符號引用,並且檢查該符號引用代表的類是否已被載入、解析和初始化過(實際上就是在檢查new的物件所屬的類是否已經執行過類載入機制)。如果沒有,先進行類載入機制載入類。關於類載入機制,之後再說。
  • 分配記憶體
    • 把一塊兒確定大小的記憶體從Java堆中劃分出來
  • 初始化零值(操作例項資料部分--物件記憶體佈局三部分之一
    • 物件的例項欄位不需要賦初始值也可以直接使用其預設零值,就是這裡起得作用
    • 每一種型別的物件都有不同的預設零值
  • 設定物件頭(操作物件頭部分--物件記憶體佈局三部分之一
  • 執行<init>
    • 為物件的欄位賦值(在第三步只是初始化了零值,這裡會根據所寫程式給例項賦值)

2、記憶體分配概念

  • 在類載入完成後,一個物件所需的記憶體大小就可以完全確定了,具體的情況檢視物件的記憶體佈局。
  • 為物件分配空間,即把一塊兒確定大小
    (上述確定下來的物件記憶體大小)的記憶體從Java堆中劃分出來

 

3、記憶體分配兩種方式

  • 指標碰撞
    • 適用場合:堆記憶體規整(即沒有記憶體碎片)的情況下
    • 原理:用過的記憶體全部整合到一邊,沒有用過的記憶體放在另一邊,中間有一個分界值指標,只需要向著沒用過的記憶體方向將該指標移動物件記憶體大小位置即可
    • GC收集器:Serial、ParNew
  • 空閒列表
    • 適用場合:堆記憶體不規整的情況下
    • 原理:虛擬機器會維護一個列表,該列表中會記錄哪些記憶體塊是可用的,在分配的時候,找一塊兒足夠大的記憶體塊兒來劃分給物件例項(這一塊兒可以類比memcached的slab模型),最後更新列表記錄。關於memcached slab記憶體模型介紹檢視《
      第六章 memcached剖析
    • GC收集器:CMS
  • 注意
    • 選擇以上兩種方式中的哪一種,取決於Java堆記憶體是否規整
    • Java堆記憶體是否規整,取決於GC收集器的演算法是"標記-清除",還是"標記-整理"(也稱作"標記-壓縮"),值得注意的是,複製演算法記憶體也是規整的

4、記憶體分配併發問題

堆記憶體是各個執行緒的共享區域,所以在操作堆記憶體的時候,需要處理併發問題。處理的方式有兩種:

  • CAS+失敗重試
  • TLAB(Thread Local Allocation Buffer)
    • 原理:為每一個執行緒預先在Eden區分配一塊兒記憶體,JVM在給執行緒中的物件分配記憶體時,首先在TLAB分配,當物件大於TLAB中的剩餘記憶體或TLAB的記憶體已用盡時,再採用上述的CAS進行記憶體分配
    • -XX:+/-UseTLAB:是否使用TLAB
    • -XX:TLABWasteTargetPercent設定TLAB可佔用的Eden區的比率,預設為1%
    • JVM會根據以下三個條件來給每個執行緒分配合適大小的TLAB
      • -XX:TLABWasteTargetPercent
      • 執行緒數量
      • 執行緒是否頻繁分配物件
    • -XX:PrintTLAB:檢視TLAB的使用情況

5、總結

  • 儘量少建立物件
    • 根據第一塊兒所說,建立一個物件的過程比較複雜,耗時較多,所以儘量減少物件的建立
    • 物件建立的少,將來垃圾收集器收集的垃圾也就少,提高效率
    • 物件建立的少,佔用記憶體也就少,那麼剩餘的系統記憶體也就相對多,系統執行也就快
    • 避免在經常使用的方法中或迴圈中建立物件
  • 多個小的物件比大物件分配起來更加高效
    • 這是根據TLAB得出來的,多個小物件可以並行在各自的TLAB分配記憶體,而大物件的話,可能只能通過CAS同步來分配記憶體
  • 衡量上述兩點
  • 對於String
    • 儘量使用直接量:eg. String str = "hello";//常量會直接存在"常量池",而非String str = new String("hello");//除了將"hello"存在"常量池"之外,還會建立一個char[]
    • 不要使用String去拼接字串,會形成許多臨時字串:如下,
          String s1 = "hello1";
          String s2 = "hello2";
          String s3 = "hello3";
          String s4 = s1+s2+s3;
      View Code

      實際上,我們只想要字串s1+s2+s3,但是在上述的拼接過程中,會形成s1+s2的臨時字串。拼接字串,使用StringBuilder,該類相較於StringBuffer由於不是同步類,其執行效果會更好。

    • 儘早釋放無用物件的引用(幫助垃圾回收)
          public void info(){
              Object obj = new Object();
              System.out.println(obj.hashCode());
              obj = null;//顯式釋放無用物件
          }
      View Code

      如上邊方法所示,其中的obj是一個區域性變數,在方法執行結束後,棧幀就會出棧並被回收,棧幀中所儲存的區域性變數一起被回收掉了,所以這裡的"obj=null;"就沒用了,但是看下邊

          public void info(){
              Object obj = new Object();
              System.out.println(obj.hashCode());
              obj = null;//顯式釋放無用物件
              //下邊還有一些很耗時、很耗記憶體的操作,這些操作與obj無關
          }
      View Code

      這時候,如果我們加上了"obj=null;"這一句,那麼就有可能在方法執行結束之前,obj被回收。

    • 儘量少使用static變數,因為static變數屬於類變數,儲存於方法區,其所佔記憶體無法被垃圾回收器回收掉,除非static所屬的類被解除安裝掉。
  • 常用的物件放入快取或連線池(其實,連線池也可以看做是一個快取)
  • 考慮使用SoftReference(關於幾種引用方式,之後會說)
    • 當記憶體足夠時,功能等同於普通變數
    • 當記憶體不足時,釋放軟引用所引用的物件
    • 一般用於大陣列、大物件
    • 通過軟引用所獲取的物件可能為null(當記憶體不足時,釋放軟引用所引用的物件),在應用程式中需要顯示判斷物件是否為null,若為null,需要重建物件

相關推薦

第二 JVM記憶體分配

注意:本篇部落格,主要參考自以下四本書 《分散式Java應用:基礎與實踐》 《深入理解Java虛擬機器(第二版)》 《突破程式設計師基本功的16課》 《實戰java虛擬機器》 說明:關於JVM記憶體結構,檢視《第一章 JVM記憶體結構》,下面所講的JVM記憶體分配主要是指在Hotspot JVM下新

JAVA虛擬機器(JVM)劃重點 第二 Java記憶體區域與記憶體溢位異常 之 虛擬機器物件

本部落格參考《深入理解Java虛擬機器》(第二版)一書,提取重點知識,再加以個人的理解編寫而成。轉載請標明來源。 JAVA虛擬機器(JVM)劃重點 第二章 Java記憶體區域與記憶體溢位異常 之 虛擬機器物件 Java物件的建立 1、類載入過程

JAVA虛擬機器(JVM)劃重點 第二 Java記憶體區域與記憶體溢位異常 之 執行時資料區域

本部落格參考《深入理解Java虛擬機器》(第二版)一書,提取重點知識,再加以個人的理解編寫而成。轉載請標明來源。 JVM劃重點 第二章 Java記憶體區域與記憶體溢位異常 之 執行時資料區域 概述 執行時資料區域 程式計數器 Java虛擬機

讀《深入理解JVM兩遍》總結(純手打) 第二 Java記憶體區域

深入理解JVM總結 第二章 Java記憶體區域 2.2 執行時資料區域 2.2.1 程式計數器 可以看作當前執行緒所執行的位元組碼行號指示器。 位元組碼直譯器工作時就是通過改變這個計數器的值來選取下一條需要執行的位元組碼指令。 每一個執行緒都需要有一個獨立的程式計數

淺談JVM記憶體分配

JVM 記憶體分配   由於Java程式是交由JVM執行的,所以我們在談Java記憶體區域劃分的時候事實上是指JVM記憶體區域劃分。如下是具體java程式的執行過程:  首先Java原始碼檔案(.java字尾)會被Java編譯器編譯為位元組碼檔案(.class字尾),然後由JVM中的類

JVM記憶體分配與回收學習(2)

1、垃圾收集器什麼時候開始回收? (1)新生代有一個Eden區和兩個survivor區(From survivor 和To Survivor),每次使用Eden和其中一個Survivor(From Survivor),建立物件時,首先會將物件放入Eden區,如果放不下就會引發一次發生在新生代

JVM記憶體分配 -Xms128m -Xmx512m -XX:PermSize=128m -XX:MaxPermSize=512m

原文地址:https://blog.csdn.net/u012882327/article/details/69525166 版權宣告:博主也花了很多的心思歸納整理才分享給大家,轉載請註明出處。 https://blog.csdn.net/u012882327/article/details/6

配置Elasticsearch heap size JVM記憶體分配官方文件

https://www.elastic.co/guide/en/elasticsearch/reference/current/heap-size.html Setting the heap size 預設1G        By default,

JVM調優(二)JVM記憶體分配引數

設定最大堆記憶體 -Xmx引數指定。最大堆是新生代和老年代的大小之和的最大值,他是java應用程式的堆上限。 使用-Xmx可以設定系統的最大堆。 設定最小堆記憶體 使用-Xms可以設定系統的最小堆空間,也就是jvm啟動時,所佔據的作業系統的記憶體大小。 設定新生代

jvm記憶體分配和垃圾回收機制

問題: 1、垃圾回收目標物件? 2、什麼時間進行垃圾回收?(面試最常見的問題之一) 3、jvm怎樣進行垃圾回收? jvm記憶體分配 執行緒共享區域 1、 堆 2、方法區 執行緒私有區域 1、jvm棧 2、本地方法棧 3、程式計數器 由於虛擬機器棧,

[JVM]記憶體分配策略

1、優先分配到eden package 深入理解java虛擬機器; public class 物件優先分配到eden區 { /** * 1M的記憶體大小 */ private static final int _1MB = 1024 * 1024;

Java資料型別和不同資料型別在JVM記憶體分配

1.java資料型別分類        Java語言是強型別(Strongly typed)語言,強型別包含兩方面的含義:①所有的變數必須先宣告,後使用;②指定型別的變數只能接受型別與之匹配的值。這意味著每個變數和每個表示式都有一個在編譯時就確定的型別。  

深入理解JVM學習筆記(二十六、JVM 記憶體分配----優先分配到eden&空間分配擔保)

一、優先分配到eden 我們寫一個程式來驗證物件優先分配到eden,原始碼如下: package com.zjt.test.jvm008; public class Main { public static void main(String[] args) { b

深入理解JVM學習筆記(二十七、JVM 記憶體分配----大物件直接分配到老年代)

一、驗證 首先我們編寫如下程式 package com.zjt.test.jvm008; public class Main { public static void main(String[]

最簡單例子圖解JVM記憶體分配和回收

一、簡介 JVM採用分代垃圾回收。在JVM的記憶體空間中把堆空間分為年老代和年輕代。將大量(據說是90%以上)建立了沒多久就會消亡的物件儲存在年輕代,而年老代中存放生命週期長久的例項物件。年輕代中又被分為Eden區(聖經中的伊甸園)、和兩個Survivor區。新的物件分配是首先放在Eden區

jvm記憶體分配及物件建立和回收過程

Java歷史 2004.9 jdk1.5 tiger 自動裝箱拆箱,泛型,,註解,列舉,變長引數,增強for迴圈 spring2.x spring4.x 2006 jdk1.6 javaee Javase Javame jdk6 提供指令碼支援 提供編譯

JVM記憶體分配筆記

一、JVM執行過程 1)編寫.java檔案 2)JVM(虛擬機器)將.java檔案編譯成.class檔案 3)類載入器載入.class檔案 4)載入完畢,交由JVM執行引擎(Execution Engine)和位元組碼直譯器執行 在執行過程中,JVM會用一部分空間來儲存程式執行期間需要用到的資料

JVM-記憶體分配

Java體系中所提倡的自動記憶體管理最終可以歸結為自動化地解決兩個問題:給物件分配記憶體以及回收分配給物件的記憶體。heap(堆)區:Eden space(伊甸區)、survivor space(倖存者區)、old age(老年代)大多數情況下,物件在新生代Eden(伊甸)區

第二Java記憶體區域與記憶體溢位異常

JVM記憶體模型及特徵: 堆: 1.JVM管理記憶體中最大的一塊,被所有執行緒共享 2.唯一目的是存放物件例項和陣列 3.垃圾蒐集器管理的主要區域 4.可擴充套件,通過-Xmx和-Xms來控制 5.如果在堆中沒有記憶體完成例項分配,並且堆也無法再擴充套件時,將會丟擲OutO

第一 JVM記憶體結構

注意:本系列部落格,主要參考自以下四本書 《分散式Java應用:基礎與實踐》《深入理解Java虛擬機器(第二版)》《深入分析Java web技術內幕》《實戰java虛擬機器》 1、為什麼要了解JVM記憶體管理機制 JVM自動的管理記憶體的分配與回收,這會在不知不覺中浪費很多記憶體,導致JVM花費很多