<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      java寶典

       

      深入解析JVM原理,JVM到底是什么

      運行時數據區結構

      pic_36e15291.png

      pic_4e0c277a.png

      堆、棧、方法去的交互關系

      pic_eb96bc89.png

      1、介紹:

      《Java虛擬機規范》中明確說明:“盡管所有的方法區在邏輯上是屬于堆的一部分,但一些簡單的實現可能不會選擇去進行垃圾收集或者進行壓縮。”但對于HotSpotJVM而言,方法區還有一個別名叫做Non-Heap(非堆),目的就是要和堆分開。所以,方法區看作是一塊獨立于Java堆的內存空間。

      • 方法區(Method Area)與Java堆一樣,是各個線程共享的內存區域。

      • 方法區在JVM啟動的時候被創建,并且它的實際的物理內存空間中和Java堆區一樣都可以是不連續的。

      • 方法區的大小,跟堆空間一樣,可以選擇固定大小或者可擴展。

      • 方法區的大小決定了系統可以保存多少個類,如果系統定義了太多的類,導致方法區溢出,虛擬機同樣會拋出內存溢出錯誤:java.lang.OutofMemoryError:PermGen space (8前)或者 java.lang.OutofMemoryError:Metaspace(8以及以后)

        • 加載過多第三方jar包;Tomcat部署項目過多;大量動態的生成反射類
      • 關閉JVM就會釋放這個區域的內存。

      別稱:jdk7及以前(永久代),jdk8及以后(元空間)

      演變

      元空間的本質和永久代類似,都是對JVM規范中方法區的實現。不過元空間與永久代最大的區別在于:元空間不在虛擬機設置的內存中,而是使用本地內存。

      永久代、元空間二者并不只是名字變了,內部結構也調整了。

      2、設置方法區內存大小

      • 元數據區大小可以使用參數-XX:MetaspaceSize-XX:MaxMetaspaceSize指定,替代上述原有的兩個參數。
      • 默認值依賴于平臺。windows下,-XX:MetaspaceSize是21M,-XX:MaxMetaspaceSize的值是-1,即沒有限制。
      • 與永久代不同,如果不指定大小,默認情況下,虛擬機會耗盡所有的可用系統內存。如果元數據區發生溢出,虛擬機一樣會拋出異常OutOfMemoryError:Metaspace
      • -XX:MetaspaceSize:設置初始的元空間大小。對于一個64位的服務器端JVM來說,其默認的XX:MetaspaceSize值為21MB。這就是初始的高水位線,一旦觸及這個水位線,Full GC將會被觸發并卸載沒用的類(即這些類對應的類加載器不再存活)然后這個高水位線將會重置。新的高水位線的值取決于GC后釋放了多少元空間。如果釋放的空間不足,那么在不超過MaxMetaspaceSize時,適當提高該值。如果釋放空間過多,則適當降低該值。
      • 如果初始化的高水位線設置過低,上述高水位線調整情況會發生很多次。通過垃圾回收器的日志可以觀察到Fu11 GC多次調用。為了避免頻繁地GC,建議將-XX:MetaspaceSize設置為一個相對較高的值。

      如何解決這些OOM?

      1、要解決OOM異常或heap space的異常,一般的手段是首先通過內存映像分析工具(如Eclipse Memory Analyzer)對dump出來的堆轉儲快照進行分析,重點是確認內存中的對象是否是必要的,也就是要先分清楚到底是出現了內存泄漏(MemoryLeak)還是內存溢出(Memory Overflow)。

      2、如果是內存泄漏,可進一步通過工具查看泄漏對象到GC Roots的引用鏈。于是就能找到泄漏對象是通過怎樣的路徑與GC Roots相關聯并導致垃圾收集器無法自動回收它們的。掌握了泄漏對象的類型信息,以及GC Roots引用鏈的信息,就可以比較準確地定位出泄漏代碼的位置。

      3、如果不存在內存泄漏,換句話說就是內存中的對象確實都還必須存活著,那就應當檢查虛擬機的堆參數(-Xmx與-Xms),與機器物理內存對比看是否還可以調大,從代碼上檢查是否存在某些對象生命周期過長、持有狀態時間過長的情況,嘗試減少程序運行期的內存消耗

      3、方法區內存結構

      pic_a8ade3f3.png

      3.1、方法區所存儲的內容:

      pic_8b99a53d.png

      1、類型信息

      對每個加載的類型(類class、接口interface、枚舉enum、注解annotation),JVM在方法區中存儲以下類型信息:
      ①這個類型的完整有效名稱(全名=包名.類名)
      ②這個類型直接父類的完整有效名(對于interface或是java.lang.object,都沒有父類)
      ③這個類型的修飾符(public,abstract,final的某個子集)
      ④這個類型直接接口的一個有序列表

      2、域信息

      JVM必須在方法區中保存類型的所有域的相關信息以及域的聲明順序。

      域的相關信息包括:域名稱、域類型、域修飾符(public,private,protected, static, final, volatile, transient的某個子集)

      3、方法信息

      JVM必須保存所有方法的以下信息,同域信息一樣包括聲明順序:

      1. 方法名稱
      2. 方法的返回類型(或void)
      3. 方法參數的數量和類型(按順序)
      4. 方法的修飾符(public,private,protected,static,final,synchronized,native,abstract的一個子集)
      5. 方法的字節碼(bytecodes)、操作數棧、局部變量表及大小(abstract和native方法除外)
      6. 異常表(abstract和native方法除外):每個異常處理的開始位置、結束位置、代碼處理在程序計數器中的偏移地址、被捕獲的異常類的常量池索引

      查看 命令行輸入 javap -v -p(包含private權限) xxx.class > xxx.txt

      示例:

      public class Test extends HashMap implements Serializable {
          private String name = "";
          private int x = 1;
          public Test(String name) {
              this.name = name;
          }
      
          public static void main(String[] args) {
              Test haha = new Test(null);
              int nameLength = haha.getNameLength();
              System.out.println(nameLength);
          }
      
          public int getNameLength() {
              int y = 0;
              try {
                  y = name.length();
              } catch (NullPointerException e) {
                  System.out.println("空指針異常");
                  e.printStackTrace();
              }
              return y;
          }
      }
      
      Classfile /D:/ideaFiles/Algorithm/out/production/Algorithm/com/lx/mySort/Test.class
        Last modified 2020-7-29; size 1145 bytes
        MD5 checksum 8f9825153f3fa6f2042785c0df59703b
        Compiled from "Test.java"
      //類信息
      public class com.lx.mySort.Test extends java.util.HashMap implements java.io.Serializable
        minor version: 0
        major version: 52
        flags: ACC_PUBLIC, ACC_SUPER
      Constant pool:
         #1 = Methodref          #15.#44        // java/util/HashMap."<init>":()V
         #2 = String             #45            //
       ...
      {
      //域信息
        private java.lang.String name;
          descriptor: Ljava/lang/String;
          flags: ACC_PRIVATE
      
        private int x;
          descriptor: I
          flags: ACC_PRIVATE
      
      //方法信息
        ...
        public int getNameLength();
          descriptor: ()I
          flags: ACC_PUBLIC
          Code:
            stack=2, locals=3, args_size=1
               0: iconst_0
               1: istore_1
               2: aload_0
               3: getfield      #3                  // Field name:Ljava/lang/String;
               6: invokevirtual #10                 // Method java/lang/String.length:()I
               9: istore_1
              10: goto          26
              13: astore_2
              14: getstatic     #8                  // Field java/lang/System.out:Ljava/io/PrintStream;
              17: ldc           #12                 // String 空指針異常
              19: invokevirtual #13                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
              22: aload_2
              23: invokevirtual #14                 // Method java/lang/NullPointerException.printStackTrace:()V
              26: iload_1
              27: ireturn
      //異常表
            Exception table:
               from    to  target type
                   2    10    13   Class java/lang/NullPointerException
            LineNumberTable:
              line 26: 0
              line 28: 2
              line 32: 10
              line 29: 13
              line 30: 14
              line 31: 22
              line 33: 26
            LocalVariableTable:
              Start  Length  Slot  Name   Signature
                 14      12     2     e   Ljava/lang/NullPointerException;
                  0      28     0  this   Lcom/lx/mySort/Test;
                  2      26     1     y   I
            StackMapTable: number_of_entries = 2
              frame_type = 255 /* full_frame */
                offset_delta = 13
                locals = [ class com/lx/mySort/Test, int ]
                stack = [ class java/lang/NullPointerException ]
              frame_type = 12 /* same */
      }
      SourceFile: "Test.java"
      
      4、靜態變量
      • non-final的類變量

        static靜態變量:加載時準備階段(賦默認值)、初始化階段賦給定值

      • 全局常量

      static final:編譯時(準備階段)賦給定值

      5、運行時常量池
      常量池

      常量池所在位置

      pic_354796b4.png

      一個有效的字節碼文件中除了包含類的版本信息、字段、方法以及接口等描述信息外,還包含一項信息那就是常量池表(Constant Pool Table),包括各種字面量和對類型、域和方法的符號引用。

      常量池的作用:

      一個java源文件中的類、接口,編譯后產生一個字節碼文件。而Java中的字節碼需要數據支持,通常這種數據會很大以至于不能直接存到字節碼里,換另一種方式,可以存到常量池,這個字節碼包含了指向常量池的引用。在動態鏈接的時候會用到運行時常量池,之前有介紹。

      常量池存儲的數據

      1. 數量值
      2. 字符串值
      3. 類引用
      4. 字段引用
      5. 方法引用
      運行時常量池
      • 運行時常量池(Runtime Constant Pool)是方法區的一部分。

      • 常量池表(Constant Pool Table)是class文件的一部分。

      • 運行時常量池,在加載類和接口到虛擬機后,就會創建對應的運行時常量池。

      • JVM為每個已加載的類型(類或接口)都維護一個常量池。

      • 運行時常量池中包含多種不同的常量,包括編譯期就已經明確的數值字面量,也包括到運行期解析后才能夠獲得的方法或者字段引用。此時不再是常量池中的符號地址了,這里換為真實地址。

        • 運行時常量池,相對于class文件常量池的另一重要特征是:具備動態性。
      • 當創建類或接口的運行時常量池時,如果構造運行時常量池所需的內存空間超過了方法區所能提供的最大值,則JVM會拋OutOfMemoryError異常。

      4、演進過程

      pic_1ae0786d.png

      pic_aad38eef.png

      pic_d44ffc41.png

      pic_66c233c9.png

      永久代為什么會被元空間替換

      • 永久代空間大小很難確定,太小容易GC/OOM異常,太大占用內存(元空間并不在虛擬機中、而是使用本地內存,大小僅受本地內存限制)
      • 永久代調優困難
      • 垃圾回收頻率低

      靜態變量放到哪里?

      堆空間里的永久代(7及后是堆)

      5、方法區的垃圾回收

      主要回收:

      1、常量池中廢棄的常量:字面量和符號引用...(沒用被引用,則可以進行回收)

      2、不再使用的類型(同時滿足以下三個條件的類可被允許回收):

      1)該類的所有實例都被回收了,即Java堆中不存在該類及其任何派生的子類的實例

      2)該類的類加載器已經被回收了(除非精心設計,否則很難實現,如OSGI,JSP的重加載等)

      3)該類對象對應的java.lang.Class對象沒有在任何地方引用、無法在任何地方通過反射訪問到該類的方法

      關于是否要對類型進行回收,HotSpot虛擬機提供了-Xnoclassgc參數進行控制,還可以使用-verbose:class以及
      -XX:+TraceClass-Loading、-XX:+TraceClassUnLoading查看類加載和卸載信息

      5、小結

      pic_990eb495.png

      6、對象實例化

      pic_ab37993d.png

      pic_2422d67f.png

      pic_e424fbbd.png

      pic_c33cb067.png

      pic_bacf0362.png

      pic_db39065e.png初始化:

      1. 默認初始化
      2. 顯示初始化 / 代碼塊初始化 / 構造器初始化

      7、對象的內存布局:

      pic_37d5131b.png

      示例:

      pic_ef4aab63.png

      pic_395fb813.png

      8、對象的訪問定位

      pic_9f6e2c9f.png

      8.1、訪問對象的方式:

      1. 句柄訪問

        reference中存儲穩定句柄地址,對象被移動(垃圾回收時常見)時只會改變句柄池中到對象示例數據的指針即可,reference不用修改

      pic_2ef9af07.png

      1. 直接指針(HotSpot采用)

        內存相對于較小

      pic_8ae7c72b.png

      9、直接內存

      • 不是虛擬機運行時數據區的一部分,也不是《Java虛擬機規范》中定義的內存區域。

      • 直接內存是在Java堆外的、直接向系統申請的內存區間。

      • 來源于NIO,通過存在堆中的DirectByteBuffer操作Native內存

      • 通常,訪問直接內存的速度會優于Java堆。即讀寫性能高。

        • 因此出于性能考慮,讀寫頻繁的場合可能會考慮使用直接內存。
        • Java的NIO庫允許Java程序使用直接內存,用于數據緩沖區

      關注公眾號:java寶典

      a

      posted on 2021-03-08 13:58  java寶典  閱讀(717)  評論(0)    收藏  舉報

      導航

      主站蜘蛛池模板: 亚洲色丰满少妇高潮18p| 国产精品免费无遮挡无码永久视频 | 国产精品揄拍一区二区久久| 沁源县| 亚洲最大成人免费av| 国产精品午夜无码AV天美传媒| 日本一区二区三区免费播放视频站| 国产一区在线播放av| 亚洲爆乳少妇无码激情| 99精品高清在线播放| 久久精品国产一区二区蜜芽| 国产精品综合一区二区三区| 国产精品人成视频免| 国产在线精品一区二区夜色| www久久只有这里有精品| 辽宁省| 国产网友愉拍精品视频手机| 丁香花成人电影| 无码精品人妻一区二区三区老牛| 丁香五月天综合缴情网| 国产乱人偷精品人妻a片| av日韩在线一区二区三区| 国产成人无码免费视频在线| 亚洲高清成人av在线| 一本高清码二区三区不卡| 亚洲午夜伦费影视在线观看| 久久精品丝袜高跟鞋| 人人妻人人狠人人爽天天综合网 | 午夜av高清在线观看| 久久五月丁香合缴情网| 四虎永久在线高清免费看| 久久久久综合中文字幕| 亚洲日本va午夜中文字幕久久 | gogogo高清免费观看| 亚洲欧美日韩久久一区二区| √天堂资源地址在线官网| 亚洲五月天一区二区三区| 亚洲熟妇少妇任你躁在线观看无码| 久久免费网站91色网站| 又污又黄又无遮挡的网站| 午夜成人鲁丝片午夜精品|