<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                ## 1. 內存結構 ### 1.1 堆內存 ![](https://img.kancloud.cn/da/18/da18761d3197e58670c9dffbb2c9abc8_598x411.png) * 永久代在jdk8之后被廢棄掉,取而代之的是元空間(MetaSpace)。 * 元空間與永久代類似,都是方法區的實現,最大的區別是:元空間不在jvm中,而使用本地內存 1. JVM內存劃分為堆內存和非堆內存,堆內存分為年輕代(Young Generation)、老年代(Old Generation),非堆內存就一個永久代(Permanent Generation)。 2. 年輕代又分為Eden和Survivor區。Survivor區由FromSpace和ToSpace組成。Eden區占大容量,Survivor兩個區占小容量,默認比例是8:1:1。 3. 堆內存用途:存放的是對象,垃圾收集器就是收集這些對象,然后根據GC算法回收。 **4. 非堆內存用途:永久代,也稱為方法區,存儲程序運行時長期存活的對象,比如類的元數據、方法、常量、屬性等**。 ### 1.2 方法區 方法區是java jvm規范,具體實現 jdk 1.7 :永久代,jdk1.8:元空間 > 方法區是jvm規范的一個概念定義,每一個jvm都有自己的實現。存儲著**類信息**、**常量**、**靜態變量** 1. 在Java官方的HotSpot 虛擬機中,Java8版本以后,是用元空間來實現的方法區;在Java8之前的版本,則是用永久代實現的方法區; 2. 也就是說,“元空間” 和 “方法區”,一個是HotSpot 的具體實現技術,一個是JVM規范的抽象定義; 所以,并不能說“JVM的元空間是方法區”,但是可以說在Java8以后的HotSpot 中“元空間用來實現了方法區”。 這個元空間是使用本地內存(Native Memory)實現的,也就是說它的內存是不在虛擬機內的,所以可以理論上物理機器還有多個內存就可以分配,而不用再受限于JVM本身分配的內存了。 #### 1.2.1 常量池 * 常量池是方法區中的一部分,一個jvm只有一個常量池,線程共享 * 保存了在編譯期間就已經確定的數據。包括final常量值(局部常量、成員常量以及引用常量)和對象字面值; * final常量:一切經過final關鍵字修飾的變量均為常量,final常量在定義時必須賦初值,否則編譯不通過; * **Java 基本類型的包裝類的大部分都實現了常量池技術,即 Byte,Short,Integer,Long,Character,Boolean;前面 4 種包裝類默認創建了數值\[-128,127\] 的相應類型的緩存數據,Character創建了數值在\[0,127\]范圍的緩存數據,Boolean 直接返回True Or False。如果超出對應范圍仍然會去創建新的對象.** **兩種浮點數類型的包裝類 Float,Double 并沒有實現常量池技術。** ``` Integer i1 = 33; Integer i2 = 33; System.out.println(i1 == i2);// 輸出 true Integer i11 = 333; Integer i22 = 333; System.out.println(i11 == i22);// 輸出 false Double i3 = 1.2; Double i4 = 1.2; System.out.println(i3 == i4);// 輸出 false ``` `Integer i1=40`;Java 在編譯的時候會直接將代碼封裝成 `Integer i1=Integer.valueOf(40)`;,從而使用常量池中的對象。 `Integer i1 = new Integer(40);`這種情況下會創建新的對象。 ``` Integer i1 = 40; Integer i2 = new Integer(40); System.out.println(i1==i2);//輸出 false ``` ``` Integer i1 = 40; Integer i2 = 40; Integer i3 = 0; Integer i4 = new Integer(40); Integer i5 = new Integer(40); Integer i6 = new Integer(0); System.out.println("i1=i2 " + (i1 == i2));//true System.out.println("i1=i2+i3 " + (i1 == i2 + i3));//true System.out.println("i1=i4 " + (i1 == i4));//false System.out.println("i4=i5 " + (i4 == i5));//false System.out.println("i4=i5+i6 " + (i4 == i5 + i6)); //true 拆箱實際上等同40==40 System.out.println("40=i5+i6 " + (40 == i5 + i6)); //true ``` 語句 i4 == i5 + i6,因為+這個操作符不適用于 Integer 對象,首先 i5 和 i6 進行自動拆箱操作,進行數值相加,即 i4 == 40。然后 Integer 對象無法與數值進行直接比較,所以 i4 自動拆箱轉為 int 值 40,最終這條語句轉為 40 == 40 進行數值比較。 #### 1.2.2 字符串常量池 常量池存在于方法區當中。 * **String s1 = new String("abc");這句話創建了幾個字符串對象?** **將創建 1 或 2 個字符串。如果池中已存在字符串常量“abc”,則只會在堆空間創建一個字符串常量“abc”。如果池中沒有字符串常量“abc”,那么它將首先在池中創建,然后在堆空間中創建,因此將創建總共 2 個字符串對象。** ``` String s1 = new String("abc");// 堆內存的地址值 String s2 = "abc"; System.out.println(s1 == s2);// 輸出 false,因為一個是堆內存,一個是常量池的內存,故兩者是不同的。 System.out.println(s1.equals(s2));// 輸出 true ``` ## 2. 堆分代 1. 新生成的對象首先放到年輕代Eden區 2. 當Eden空間滿了,觸發Minor GC,存活下來的對象移動到Survivor0區 3. Survivor0區滿后觸發執行Minor GC,Survivor0區存活對象移動到Suvivor1區,這樣保證了一段時間內總有一個survivor區為空。經過多次Minor GC仍然存活的對象移動到老年代。 4. 老年代存儲長期存活的對象,占滿時會觸發Major GC=Full GC,GC期間會停止所有線程等待GC完成,所以對響應要求高的應用盡量減少發生Major GC,避免響應超時。 Minor GC : 清理年輕代 Major GC : 清理老年代 Full GC : 清理整個堆空間,包括年輕代和永久代 **所有GC都會停止應用所有線程** ## 3.為什么會堆內存溢出? > **在年輕代中經過GC后還存活的對象會被復制到老年代中。當老年代空間不足時,JVM會對老年代進行完全的垃圾回收(Full GC)。如果GC后,還是無法存放從Survivor區復制過來的對象,就會出現OOM(Out of Memory)。** **OOM(Out of Memory)異常常見有以下幾個原因:** 1)老年代內存不足:java.lang.OutOfMemoryError:Javaheapspace 2)永久代內存不足:java.lang.OutOfMemoryError:PermGenspace 3)代碼bug,占用內存無法及時回收。 OOM在這幾個內存區都有可能出現,實際遇到OOM時,能根據異常信息定位到哪個區的內存溢出。 ## 4. 內存溢出排查方法 1 . 分析堆內存快照 可以通過添加個參數-XX:+HeapDumpOnOutMemoryError,讓虛擬機在出現內存溢出異常時Dump出當前的內存堆轉儲快照以便事后分析。 2. Java工具 **jstat分析各塊內存占用率和gc時間** ![](https://img.kancloud.cn/16/b1/16b1918061c06dd0d9384de8caef222c_860x301.png) 查詢結果表明:這臺服務器的新生代Eden區(E,表示Eden)使用了28.30%(最后)的空間,兩個Survivor區(S0、S1,表示Survivor0、Survivor1)分別是0和8.93%,老年代(O,表示Old)使用了87.33%。程序運行以來共發生Minor GC(YGC,表示Young GC)101次,總耗時1.961秒,發生Full GC(FGC,表示Full GC)7次,Full GC總耗時3.022秒,總的耗時(GCT,表示GC Time)為4.983秒。 jmap查看對象存活狀態,實例個數和占用內存 ``` jmap -histo:live 1002 ``` ![](https://img.kancloud.cn/dc/9a/dc9ad6c116faa38af80f9348b1803df9_813x411.png)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看