欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

簡單說說JVM堆區(qū)的相關知識

 更新時間:2021年06月22日 15:24:05   作者:ayugudu  
今天給大家?guī)淼氖顷P于Java虛擬機的相關知識,文章圍繞著JVM堆區(qū)展開,文中有非常詳細的介紹及代碼示例,需要的朋友可以參考下

一、堆概述

  • 一個jvm實例(進程)只存在一個堆內存,堆也是java內存管理的核心區(qū)域。
  • java 堆區(qū)在jvm啟動時即被創(chuàng)建,其空間大小也就被確定了
  • 《java虛擬機規(guī)范》規(guī)定,堆可以處于物理上不連續(xù)的內存空間,但在邏輯上它應該被稱為連續(xù)的
  • 所有線程共享java堆,在這里和可以劃分線程私有的緩沖區(qū)(tlab)
  • 所有對象實例以及數(shù)組都應在運行時分配在堆中
  • 方法結束后,堆中的對象不會馬上被移除,僅僅在垃圾收集時候才會被移除
  • 堆是gc執(zhí)行垃圾回收的重點區(qū)域

1.1 堆內存細分

現(xiàn)代垃圾收集器大部分基于分代收集理論設計,堆空間細分為:

  • java 7 之前堆內存邏輯分為:新生區(qū)+老年區(qū)+永久區(qū)
  • java 8 之后內存邏輯上分為:新生區(qū)+老年區(qū)+元空間

使用下面命令設置堆空間初始化 10m,最大空間 10m

-Xms10m -Xmx10m

使用java visual 查看 visual gc

可以看出通過參數(shù)設置的內存大小 只與新生代(Eden+s0+s1 ),老年代有關,而在邏輯上還要加上元空間。

1.2 堆空間大小的設置

1.2.1 通過參數(shù)設置

-Xms 用來設置堆空間(年輕代+老年代)的初始內存大小
  -X 是jvm的運行參數(shù)
  ms 是memory start
  
-Xmx 用來設置堆空間(年輕代+老年代)的初始內存大小
  • 一旦堆區(qū)中的內存大小超過“-Xmx”所指定的最大內存時,將會拋出OutOfMemoryError異常。
  • 通常會將 -Xms 和 -Xmx 兩個參數(shù)配置相同的值,其目的是為了能夠在java垃圾回收機制清理完堆區(qū)后不需要重新分隔計算堆區(qū)的大小,從而提高性能

1.2.2 默認空間大小

  • 初始化內存大小為物理內存的 1/64
  • 最大內存大小為物理內存大小 1/4

使用一下代碼查看 當前jvm初始化內存與最大內存

/**
 * @program: jvmDemo
 * @description:
 * @author: wfg
 * @create: 2021-06-14 10:40
 */
public class Test9 {

    public static void main(String[] args) {
        //返回jvm中的內存總量(字節(jié))
          long initialMemory = Runtime.getRuntime().totalMemory()/1024/1024;
        //虛擬機將嘗試使用最大堆內存
         long maxMemory = Runtime.getRuntime().maxMemory()/1024/1024;
        System.out.println("-Xms:"+initialMemory+"m");

        System.out.println("-Xmx:"+maxMemory+"m");


        System.out.println("系統(tǒng)大?。?+initialMemory*64/1024+"G");
        System.out.println("系統(tǒng)大?。?+maxMemory*4/1024+"G");

    }

}

結果(本機運行內存為 8g)

1.2.3 通過參數(shù)設置堆空間大小后內存不一致問題

設置300

查看

/**
 * @program: jvmDemo
 * @description:
 * @author: wfg
 * @create: 2021-06-14 10:40
 */
public class Test9 {

    public static void main(String[] args) {
        //返回jvm中的內存總量(字節(jié))
        long initialMemory = Runtime.getRuntime().totalMemory() / 1024 / 1024;
        //虛擬機將嘗試使用最大堆內存
        long maxMemory = Runtime.getRuntime().maxMemory() / 1024 / 1024;
        
        System.out.println("-Xms:" + initialMemory + "m");

        System.out.println("-Xmx:" + maxMemory + "m");
        
    }

}

結果

分析

在vm參數(shù)設置里面加上

-XX:+PrintGCDetails 

再次運行程序查看

原理

新生代的s0 和 s1 只能有一個生效

1.3 年輕代與年老代

  • 存儲在jvm中的java對象可以劃分為兩類:

一類是生命周期較短的瞬時對象。

另外一類是對象生命周期非常長。

  • jvm堆區(qū)再次進行細分可以分為 年輕代與老年代
  • 其中年輕代可以劃分為Eden空間,survivor0空間和survivor1空間(有時也叫 from區(qū),to區(qū))

  • 新生代與老年代空間大小 默認是 1:2

可以通過 -XX:NewRation設置新生代與老年代的比例,默認值是2.(一般都不會去設置)

  • Eden與s0,s1 的內存默認分配比例為 8:1:1

1.4 對象分配過程

1.new的對象先放伊甸區(qū),此區(qū)有大小限制

2.當伊甸區(qū)滿的時候,程序需要創(chuàng)建時,jvm的垃圾回收將對伊甸園區(qū)進行垃圾回收(minor gc)

3.然后將伊甸園中的剩余對象移動到辛存者0

4.如果再次觸發(fā)垃圾回收,上次幸存下來的放到幸存者0區(qū),沒有回收,就會放到幸存者1區(qū)

5.再次經(jīng)歷垃圾回收會重新放回辛存者0區(qū)

6.當在辛存者區(qū)達到15次時,就可以去老年區(qū)了

可以設置參數(shù):-XX:MaxTenuringThreshold=

7.當養(yǎng)老區(qū)內存不足時,再次觸發(fā)GC:major GC,進行養(yǎng)老區(qū)的內存處理

8.若養(yǎng)老區(qū)進行處理后,依然無法進行對象的保存,就會產(chǎn)生00m異常

java.lang.outofMemoryError:java heap space

9.總結

  • 針對幸存者s0,s1區(qū)總結:復制之后有交換誰空誰是to
  • 垃圾回收:頻繁在新生區(qū)收集,很少在養(yǎng)老區(qū)收集,幾乎不再永久區(qū)/元空間收集

10.流程

當Eden滿時,會觸發(fā)MinorGC算法來回收memory,旨在清理掉再無引用的數(shù)據(jù)(在內存里是Tree),意圖存儲到S0. 若此時S0也滿了,會再次MinorGC意圖回收S0無引用的數(shù)據(jù),把有引用的數(shù)據(jù)移動到S1。如果S1夠用,此時會清空S0;如果S1滿了,會回滾剛存入S1的數(shù)據(jù),直接把本次GC的數(shù)據(jù)存入Old區(qū),S0保持剛剛MinorGC時的狀態(tài)。延伸:如果Old也滿了,會觸發(fā)MajorGC,如果還是不夠,則存入Permanent Generate,不幸這里也滿了,會在允許的范圍內按照內置的規(guī)則自動增長,可能不會發(fā)生GC,也可能會。當增長的量不夠存時,會觸發(fā)Full GC。若FullGC后還是不夠存,自動增長的量也超過了允許的范圍,則發(fā)生內存溢出。還有一種情況,就是分配的線程棧處于很深的遞歸或死循環(huán)時,會發(fā)生棧內存溢出。

二、對象分配過程:Tlab

2.1 為什么要有tlab

  • 堆區(qū)是線程共享的,任何線程都可以訪問到堆區(qū)中的共享數(shù)據(jù)
  • 由于對象實例的創(chuàng)建在jvm中非常頻繁,因此在并發(fā)環(huán)境下從堆區(qū)中劃分內存空間是不安全的
  • 而加鎖會影響分配速度

2.2什么是tlab

  • 從內存模型而不是垃圾收集角度,對eden區(qū)域進行劃分,jvm為每個線程分配了一個私有緩存區(qū)域
  • 多線程同時分配內存時,使用tlab可以避免非線程安全問題,同時還能夠提升內存分配的吞吐量,因此我們將其稱為 快速分配策略
  • jvm將tlab作為內存分配的首選
  • 在程序中可以通過參數(shù)-XX:UseTLAB設置是否開啟(默認是開啟的)
  • tlab僅占有eden空間大小的1%,可以通過-XX:TLABWasteTargetPercent設置tlab空間所占用eden空間的大小
  • 使用tlab空間分配內存失敗時,jvm會使用加鎖機制確保操作的原子性

對象分配流程

對象分配流程

三、堆空間常用參數(shù)設置

  •  -XX:+PrintFlagsInitial: 查看所有參數(shù)的默認初始值
  • -XX:+PrintFlagFinal: 查看所有參數(shù)的最終值
  • -Xms::初始化堆空間內存(默認為物理內存的1/64)
  • -Xmx: 最大堆空間內存(默認為物理內存的1/4)
  • -Xmn:設置新生代的大小(初始值及最大值)
  • -XX:NewRatio: 配置新生代與老年代在堆結構的占比
  • -XX:SurvivorRatio:設置新生代中 eden和s0、s1空間的比例
  • -XX:MaxTenuringThreshold:設置新生代垃圾最大的年齡
  • -XX:+PrintGCDetails:輸出詳細的gc處理日志
  • -XX:+PrintGC:輸出簡要的gc處理日志

四、堆是分配對象的唯一選擇嗎

  1. 隨著jit編譯期的發(fā)展與逃逸分析技術成熟,棧上分配與標量替換優(yōu)化技術導致所有對象都分配到堆上不那么絕對了
  2. 如果經(jīng)過逃逸分析后發(fā)現(xiàn),一個對象并沒有逃逸出方法的話,那么可能被優(yōu)化成棧上分配

4.1 逃逸分析

  • 當一個對象在方法中被定義后,對象只在方法內部使用,則認為沒有發(fā)生逃逸。
  • 當一個對象在方法中被定義后,被外部方法所引用,則認為發(fā)生逃逸了

判斷逃逸的方法:看new 的對象實體是否有可能在方法外被調用

在這里插入圖片描述

4.2 代碼優(yōu)化

  • 棧上分配。將堆分配轉化為棧分配。
  • 同步省略。如果一個對象被發(fā)現(xiàn)只能從一個線程被訪問到,那么對于這個對象的操作可以不考慮同步
  • 分離對象或標量替換。有的對象可能不需要作為一個連續(xù)的內存結構存在也可以被訪問到,那么對象的部分可以不存儲在內存,而是存儲在cpu寄存器中。
  •  標量是指一個無法在分解成更小的數(shù)據(jù),相對的其它還可以在分解的稱為聚合量
  • 在jit階段進行逃逸分析,發(fā)現(xiàn)對象不會被外界訪問(沒有逃逸發(fā)生),經(jīng)過jit優(yōu)化,就回把對象分解為成員變量來代替,這個過程就是標量替換

到此這篇關于簡單說說JVM堆區(qū)的相關知識的文章就介紹到這了,更多相關JVM堆區(qū)內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Java實現(xiàn)PDF在線預覽功能(四種方式)

    Java實現(xiàn)PDF在線預覽功能(四種方式)

    這篇文章主要介紹了Java實現(xiàn)PDF在線預覽功能的四種方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • WebSocket實現(xiàn)聊天室業(yè)務

    WebSocket實現(xiàn)聊天室業(yè)務

    這篇文章主要為大家詳細介紹了WebSocket實現(xiàn)聊天室業(yè)務,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-08-08
  • Java游戲俄羅斯方塊的實現(xiàn)實例

    Java游戲俄羅斯方塊的實現(xiàn)實例

    這篇文章主要介紹了Java游戲俄羅斯方塊的實現(xiàn)實例的相關資料,這里實現(xiàn)簡單的俄羅斯方塊幫助大家學習理解基礎知識,需要的朋友可以參考下
    2017-08-08
  • 簡述Java中的四種引用類型

    簡述Java中的四種引用類型

    從JDK1.2版本開始,把對象的引用分為四種級別,從而使程序能更加靈活的控制對象的生命周期。這四種級別由高到低依次為:強引用、軟引用、弱引用和虛引用,下面分別介紹下這四種引用。
    2021-04-04
  • 解決@RequestMapping和@FeignClient放在同一個接口上遇到的坑

    解決@RequestMapping和@FeignClient放在同一個接口上遇到的坑

    這篇文章主要介紹了解決@RequestMapping和@FeignClient放在同一個接口上遇到的坑,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • springBoot熱部署、請求轉發(fā)與重定向步驟詳解

    springBoot熱部署、請求轉發(fā)與重定向步驟詳解

    這篇文章主要介紹了springBoot熱部署、請求轉發(fā)與重定向,本文通過示例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-06-06
  • SpringBoot+thymeleaf+Echarts+Mysql 實現(xiàn)數(shù)據(jù)可視化讀取的示例

    SpringBoot+thymeleaf+Echarts+Mysql 實現(xiàn)數(shù)據(jù)可視化讀取的示例

    本文主要介紹了SpringBoot+thymeleaf+Echarts+Mysql 實現(xiàn)數(shù)據(jù)可視化讀取的示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-04-04
  • Java實現(xiàn)多選批量刪除功能(vue+Element)

    Java實現(xiàn)多選批量刪除功能(vue+Element)

    這篇文章主要為大家詳細介紹了Java實現(xiàn)多選批量刪除功能,包括前端vue實現(xiàn)代碼文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • Java并發(fā)編程總結——慎用CAS詳解

    Java并發(fā)編程總結——慎用CAS詳解

    下面小編就為大家?guī)硪黄狫ava并發(fā)編程總結——慎用CAS詳解。小編覺得挺不錯的, 現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-06-06
  • SpringMVC之異常處理解讀

    SpringMVC之異常處理解讀

    這篇文章主要介紹了SpringMVC之異常處理解讀,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-03-03

最新評論