久久精品国产精品国产精品污,男人扒开添女人下部免费视频,一级国产69式性姿势免费视频,夜鲁夜鲁很鲁在线视频 视频,欧美丰满少妇一区二区三区,国产偷国产偷亚洲高清人乐享,中文 在线 日韩 亚洲 欧美,熟妇人妻无乱码中文字幕真矢织江,一区二区三区人妻制服国产

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

JVM系统学习

發布時間:2023/12/31 windows 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JVM系统学习 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 為什么要學習JVM
  • Java內存區域
    • 運行時數據區域
      • 方法區的變化
      • 數據的遷移
      • 元空間簡介
        • 元數據
        • 為什么移除永久代?
        • 為什么要引入元空間
      • 程序計數器
      • Java 虛擬機棧
      • 本地方法棧
      • 方法區
        • 方法區和永久代的關系
        • 常用參數
        • 元空間
      • 運行時常量池
      • 直接內存
    • HotSpot虛擬機對象探秘
      • 對象的創建
        • Step1:類加載檢查
        • Step2:分配內存
        • Step3:初始化零值
        • Step4:設置對象頭
        • Step5:執行 init 方法
      • 對象的內存布局
        • 對象頭
          • 對象自身的運行時數據
          • 類型指針
        • 實例數據
        • 對齊填充
      • 對象的訪問定位
      • String 類和常量池
        • 字符串拼接:
        • 小問題
      • 8 種基本類型的包裝類和常量池
      • 參考鏈接
  • 垃圾收集器與內存分配策略
    • 本章常見面試題
    • 導論
    • 概述
    • JVM內存分配和回收基礎
      • 對象優先在 eden 區分配
      • 大對象直接進入老年代
      • 長期存活的對象將進入老年代
      • 動態對象年齡判定
      • 空間分配擔保
      • Full GC 的觸發條件
        • 1. 調用 System.gc()
        • 2. 老年代空間不足
        • 3. 空間分配擔保失敗
        • 4. JDK 1.7 及以前的永久代空間不足
        • 5. Concurrent Mode Failure
    • 對象已死?
      • 引用計數法
      • 可達性分析算法
        • GC Roots
      • 再談引用
        • 強引用
        • 軟引用
        • 弱引用
          • 應用
          • WeakHashMap
          • ReferenceQueue
        • 虛引用
          • PhantomReference
      • 生存還是死亡?
      • 回收方法區
        • 如何判斷一個常量是廢棄常量
        • 如何判斷一個類是無用的類
    • OOM
      • Java.lang.StackOverflowError
      • Java.lang.OutOfMemoryError: Java heap space
      • Java.lang.OutOfMemoryError: GC overhead limit exceeded
      • Java.lang.OutOfMemoryError: Direct buffer memory
      • Java.lang.OutOfMemoryError: unable to create new native thread
        • 導致原因
        • 解決辦法
      • Java.lang.OutOfMemoryError: Metaspace
    • 垃圾收集算法
      • 分代收集理論
      • 標記-清除算法
      • 標記-復制算法
      • 標記-整理算法
    • HotSpot的算法細節實現
    • 經典垃圾收集器
      • 1.新生代的收集器包括
      • 2.老年代的收集器包括
      • 3.回收整個Java堆(新生代和老年代)
      • Serial 收集器 Serial串行收集器-復制算法
        • 總結
          • 優勢:
          • 劣勢:
          • 使用場景
      • ParNew 收集器 復制算法
        • 小結
          • 優勢:
          • 劣勢:
          • 使用場景
      • Parallel Scavenge 收集器 (并行回收)收集器-復制算法
        • 小結
          • 有如下特點:
          • 優勢:
          • 劣勢:
          • 使用場景
      • Serial Old 收集器 標記整理算法
        • 小結
          • 特點
          • 使用場景
      • Parallel Old收集器 收集器-標記整理算法
      • CMS 收集器 標記整理算法
        • 小結
          • 特點:
          • 優勢:
          • 劣勢:
      • G1 收集器
      • ZGC
      • 查看當前使用的垃圾收集器
      • 一些參數
      • 配置垃圾收集器
      • 如何選擇垃圾收集器
    • 低延遲垃圾收集器
      • Shenandoah收集器
      • ZGC收集器
    • 選擇合適的垃圾收集器
      • Epsilon收集器
    • JVM垃圾收集器總結
  • JVM調優
    • JVM參數類型
      • 標配參數
      • X參數
      • XX參數
        • Boolean類型
        • KV設值類型
        • jinfo舉例,如何查看當前運行程序的配置
    • JVM常用配置參數
      • -Xms 和 -Xmx
      • -Xss
      • -Xmn
      • -XX:MetaspaceSize
      • -XX:+PrintGCDetails
        • Minor GC
        • Full GC
      • 設置參數案例
      • -XX:SurvivorRatio
      • -XX:NewRatio
      • -XX:MaxTenuringThreshold
    • 如何查看JVM系統默認值
  • 類文件結構
    • 概述
    • Class 文件結構總結
      • 2.1 魔數
      • 2.2 Class 文件版本
      • 2.3 常量池
      • 2.4 訪問標志
      • 2.5 當前類索引,父類索引與接口索引集合
      • 2.6 字段表集合
      • 2.7 方法表集合
      • 2.8 屬性表集合
      • 參考鏈接
  • 虛擬機類加載機制
    • 類的生命周期
    • 類加載過程
      • 加載
      • 驗證
      • 準備
      • 解析
      • 初始化
        • 主動引用
        • 被動引用
      • 卸載
      • **參考鏈接**
    • 類加載器
      • 雙親委派模型
      • 雙親委派模型實現源碼分析
      • 雙親委派模型的好處
      • 如果我們不想用雙親委派模型怎么辦?
      • 自定義類加載器
    • tomcat 為什么打破雙親委派模型
      • 參考鏈接
  • JVM調優
    • 概述
      • 為什么調優
      • 性能優化的步驟
      • 性能評價指標
    • 性能監控及診斷工具
      • jps
        • 基本語法
      • jstat
        • 基本語法
        • 判斷內存泄露
      • jinfo
        • 基本語法
      • jmap
        • 導出內存映像文件
        • 顯示堆內存相關信息
      • jat
        • 基本語法
      • Jstack(JVM Stack Trace)
      • jcmd
      • jstatd
    • 圖形化工具
      • Jconsole
      • Visual VM
      • MAT
      • tomcat
      • JProfile
      • Arthas
        • 命令
      • Java Mission Control
      • Flame Graphs
      • Tprofiler
    • 內存泄露
      • 靜態集合類
      • 單例模式
      • 內部類持有外部類
      • 各種連接
      • 變量不合理的作用域
      • 改變哈希值
      • 緩存泄漏
      • 監聽器和回調
    • JVM運行時參數
    • 分析日志
      • Minor GC日志解析
      • Full GC日志分析
      • GC Easy
      • GCViewer
    • 性能優化

為什么要學習JVM

  • 面試的需要(BATJ、TMD,PKQ等面試都愛問)

  • 中高級程序員必備技能

    • 項目管理、調優的需求
  • 追求極客的精神

    • 比如:垃圾回收算法、JIT(及時編譯器)、底層原理

Java內存區域

運行時數據區域

Java虛擬機在執行Java程序的過程中會把它所管理的內存劃分為若干個不同的數據區域。JDK 1.8和之前的版本略有不用,見下圖:

方法區的變化

JDK1.8與JDK1.7最大的區別是:JDK1.8將永久代取消,取而代之的是元空間,在JDK1.8中方法區是由元空間來實現,所以原來屬于方法區的運行時常量池就屬于元空間了。
??元空間屬于本地內存,所以元空間的大小僅受本地內存限制,但是可以通過-XX:MaxMetaspaceSize進行增長上限的最大值設置,默認值為4G,元空間的初始空間大小可以通過-XX:MetaspaceSize進行設置,默認值為20.8M,還有一些其他參數可以進行設置,元空間大小會自動進行調整。

數據的遷移

在JDK1.7之前運行時常量池,字符串常量池,靜態域等存放在方法區, 運行時常量池邏輯包含字符串常量池,此時hotspot虛擬機對方法區的實現為永久代。
??在JDK1.7中字符串常量池和靜態域被從方法區(永久代)拿到了堆中(在堆中另開辟了一塊空間),這里沒有提到運行時常量池,也就是說字符串常量池被單獨拿到堆,運行時常量池剩下的東西還在方法區,也就是hotspot中的永久代。
??在JDK1.8 hotspot移除了永久代,用元空間(Metaspace)取而代之, 這時候字符串常量池還在堆,運行時常量池還在方法區,只不過方法區的實現從永久代變成了元空間(Metaspace)。

元空間簡介

用于存儲已被虛擬機加載的類元數據,符號引用,即包括運行時常量池。元空間的本質和永久代類似,都是對JVM規范中方法區的實現。不過元空間與永久代之間最大的區別在于:元空間并不在虛擬機中,而是使用本地內存。因此,默認情況下,元空間的大小僅受本地內存限制,但可以通過以下參數來指定元空間的大小:-XX:MetaspaceSize。

元數據

元數據(Meta Date),關于數據的數據或者叫做用來描述數據的數據或者叫做信息的信息。
??這些定義都很是抽象,我們可以把元數據簡單的理解成,最小的數據單位。元數據可以為數據說明其元素或屬性(名稱、大小、數據類型、等),或其結構(長度、字段、數據列),或其相關數據(位于何處、如何聯系、擁有者)

為什么移除永久代?

由于永久代使用jvm內存經常不夠用或發生內存泄露,引發惱人的OutOfMemoryError異常(在Java Web開發中非常常見)。
移除永久代可以促進HotSpot JVM與JRockit VM兩種虛擬機的融合,因為JRockit沒有永久代。
對永久代進行調優是很困難的。永久代中的元數據可能會隨著每一次Full GC發生而進行移動。

為什么要引入元空間

字符串常量存在永久代中,容易出現性能問題和內存溢出。
類及方法的信息等比較難確定其大小,因此對于永久代的大小指定比較困難,太小容易出現永久代溢出,太大則容易導致老年代溢出。
永久代會為 GC 帶來不必要的復雜度,并且回收效率偏低。
Oracle 可能會將HotSpot與Jrockit兩種虛擬機合二為一。

線程私有的:程序計數器、虛擬機棧、本地方法棧

線程共享的:堆、方法區、直接內存

程序計數器

程序計數器是一塊較小的內存空間,可以看作是當前線程所執行的字節碼的行號指示器。字節碼解釋器工作時通過改變這個計數器的值來選取下一條需要執行的字節碼指令,分支、循環、跳轉、異常處理、線程恢復等功能都需要依賴這個計數器來完成。

另外,為了線程切換后能恢復到正確的執行位置,每條線程都需要有一個獨立的程序計數器,各線程之間計數器互不影響,獨立存儲,我們稱這類內存區域為“線程私有”的內存。

從上面的介紹中我們知道程序計數器主要有兩個作用:

  • 字節碼解釋器通過改變程序計數器來依次讀取指令,從而實現代碼的流程控制,如:順序執行、選擇、循環、異常處理。
  • 在多線程的情況下,程序計數器用于記錄當前線程執行的位置,從而當線程被切換回來的時候能夠知道該線程上次運行到哪兒了。
  • 如果線程正在執行的是一個Java方法,這個計數器記錄的是正在執行的虛擬機字節碼指令的地址;如果正在執行的是本地(Native)方法,這個計數器值則為空。

    注意:程序計數器是唯一一個不會出現 OutOfMemoryError 的內存區域,它的生命周期隨著線程的創建而創建,隨著線程的結束而死亡。

    Java 虛擬機棧

    與程序計數器一樣,Java 虛擬機棧也是線程私有的,它的生命周期和線程相同,描述的是 Java 方法執行的內存模型,每次方法調用的數據都是通過棧傳遞的。

    虛擬機棧描述的是Java方法執行的線程內存模型:每個方法執行的時候,Java虛擬機都會同步創建一個棧幀用于存儲局部變量表、操作數棧、動態鏈接、方法出口信息。每一個方法被調用直至執行完畢的過程,就對應著一個棧幀在虛擬機棧中從入棧到出棧的過程。

    局部變量表主要存放了編譯器可知的各種數據類型(boolean、byte、char、short、int、float、long、double)、對象引用(reference 類型,它不同于對象本身,可能是一個指向對象起始地址的引用指針,也可能是指向一個代表對象的句柄或其他與此對象相關的位置)和**returnAddress類型(**指向了一條字節碼指令的地址)。

    這些數據類型在局部變量表中的存儲空間以局部變量槽(Slot)來表示,其中64位長度的long和double類型的數據會占用兩個變量槽,其余類型只占用一個。局部變量表所需的內存空間在編譯期間完成分配,當進入一個方法時,這個方法需要在棧幀中分配多大的局部變量空間是完全確定的,在方法運行期間不會改變局部變量表的大小。("大小"指的是變量槽的數量)

    Java 虛擬機棧會出現兩種錯誤:StackOverFlowError 和 OutOfMemoryError。

    • StackOverFlowError: 若 Java 虛擬機棧的內存大小不允許動態擴展,那么當線程請求棧的深度超過當前 Java 虛擬機棧的最大深度的時候,就拋出 StackOverFlowError 錯誤。
    • OutOfMemoryError: 若 Java 虛擬機棧的內存大小允許動態擴展,且當線程請求棧時內存用完了,無法再動態擴展了,此時拋出 OutOfMemoryError 錯誤。

    擴展:那么方法/函數如何調用?

    Java ??捎妙惐葦祿Y構中棧,Java 棧中保存的主要內容是棧幀,每一次函數調用都會有一個對應的棧幀被壓入 Java 棧,每一個函數調用結束后,都會有一個棧幀被彈出。

    Java 方法有兩種返回方式:

  • return 語句。
  • 拋出異常。
  • 不管哪種返回方式都會導致棧幀被彈出。

    本地方法棧

    和虛擬機棧所發揮的作用非常相似,區別是: 虛擬機棧為虛擬機執行 Java 方法 (也就是字節碼)服務,而本地方法棧則為虛擬機使用到的 Native 方法服務。 在 HotSpot 虛擬機中和 Java 虛擬機棧合二為一。

    方法執行完畢后相應的棧幀也會出棧并釋放內存空間,也會出現 StackOverFlowError 和 OutOfMemoryError 兩種錯誤。

    Java 堆是Java 虛擬機所管理的內存中最大的一塊,也是所有線程共享的一塊內存區域,在虛擬機啟動時創建。此內存區域的唯一目的就是存放對象實例,幾乎所有的對象實例以及數組都在這里分配內存。

    Java 堆是垃圾收集器管理的主要區域,因此也被稱作GC 堆(Garbage Collected Heap).從垃圾回收的角度,由于現在收集器基本都采用分代垃圾收集算法,所以 Java 堆還可以細分為:新生代和老年代:再細致一點有:Eden 空間、From Survivor、To Survivor 空間等。進一步劃分的目的是更好地回收內存,或者更快地分配內存。

    在 JDK 7 版本及JDK 7 版本之前,堆內存被通常被分為下面三部分:

    • 新生代內存(Young Generation)

    • 老生代(Old Generation)

    • 永生代(Permanent Generation)

    JDK 8 版本之后方法區(HotSpot 的永久代)被徹底移除了(JDK1.7 就已經開始了),取而代之是元空間,元空間使用的是直接內存。

    上圖所示的 Eden 區、兩個 Survivor 區都屬于新生代(為了區分,這兩個 Survivor 區域按照順序被命名為 s1 和 s2),中間一層屬于老年代。

    大部分情況,對象都會首先在 Eden 區域分配,在一次新生代垃圾回收后,如果對象還存活,則會進入 s1 或者 s2,并且對象的年齡還會加 1(Eden 區->Survivor 區后對象的初始年齡變為 1),當它的年齡增加到一定程度(默認為 15 歲),就會被晉升到老年代中。對象晉升到老年代的年齡閾值,可以通過參數 -XX:MaxTenuringThreshold 來設置。

    新生代到老年代的閾值:

    Hotspot遍歷所有對象時,按照年齡從小到大對其所占用的大小進行累積,當累積的某個年齡大小超過了survivor區的一半時,取這個年齡和MaxTenuringThreshold中更小的一個值,作為新的晉升年齡閾值。

    堆這里最容易出現的就是 OutOfMemoryError 錯誤,并且出現這種錯誤之后的表現形式還會有幾種,比如:

  • OutOfMemoryError: GC Overhead Limit Exceeded : 當JVM花太多時間執行垃圾回收并且只能回收很少的堆空間時,就會發生此錯誤。
  • java.lang.OutOfMemoryError: Java heap space :假如在創建新的對象時, 堆內存中的空間不足以存放新創建的對象, 就會引發java.lang.OutOfMemoryError: Java heap space 錯誤。(和本機物理內存無關,和你配置的內存大小有關!)
  • 方法區

    方法區與 Java 堆一樣,是各個線程共享的內存區域,它用于存儲已被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯后的代碼等數據。雖然 Java 虛擬機規范把方法區描述為堆的一個邏輯部分,但是它卻有一個別名叫做 Non-Heap(非堆),目的應該是與 Java 堆區分開來。方法區也被稱為永久代。

    方法區和永久代的關系

    《Java 虛擬機規范》只是規定了有方法區這么個概念和它的作用,并沒有規定如何去實現它。那么,在不同的 JVM 上方法區的實現肯定是不同的了。方法區和永久代的關系很像 Java 中接口和類的關系,類實現了接口,而永久代就是 HotSpot 虛擬機對虛擬機規范中方法區的一種實現方式。 也就是說,永久代是 HotSpot 的概念,方法區是 Java 虛擬機規范中的定義,是一種規范,而永久代是一種實現,一個是標準一個是實現,其他的虛擬機實現并沒有永久代這一說法。

    常用參數

    JDK 1.8 之前永久代還沒被徹底移除的時候通常通過下面這些參數來調節方法區大小

    -XX:PermSize=N //方法區 (永久代) 初始大小 -XX:MaxPermSize=N //方法區 (永久代) 最大大小,超過這個值將會拋出 OutOfMemoryError 異常:java.lang.OutOfMemoryError: PermGen

    相對而言,垃圾收集行為在這個區域是比較少出現的,但并非數據進入方法區后就“永久存在”了。這區域的內存回收目標主要是針對常量池的回收和對類型的卸載,一般來說這個區域的回收效果比較好。

    JDK 1.8 的時候,方法區(HotSpot 的永久代)被徹底移除了(JDK1.7 就已經開始了),取而代之是元空間,元空間使用的是直接內存。

    下面是一些常用參數:

    -XX:MetaspaceSize=N //設置 Metaspace 的初始(和最小大小) -XX:MaxMetaspaceSize=N //設置 Metaspace 的最大大小

    與永久代很大的不同就是,如果不指定大小的話,隨著更多類的創建,虛擬機會耗盡所有可用的系統內存。

    元空間

    JDK 1.8之后使用元空間(存放在內存里)替代永久代,為什么要這樣做?

  • 整個永久代有一個 JVM 本身設置固定大小上限,無法進行調整,而元空間使用的是直接內存,受本機可用內存的限制,雖然元空間仍舊可能溢出,但是比原來出現的幾率會更小。

    當你元空間溢出時會得到如下錯誤: java.lang.OutOfMemoryError: MetaSpace

    你可以使用 -XX:MaxMetaspaceSize 標志設置最大元空間大小,默認值為 unlimited,這意味著它只受系統內存的限制。-XX:MetaspaceSize 調整標志定義元空間的初始大小如果未指定此標志,則 Metaspace 將根據運行時的應用程序需求動態地重新調整大小。

  • 元空間里面存放的是類的元數據,這樣加載多少類的元數據就不由 MaxPermSize 控制了, 而由系統的實際可用空間來控制,這樣能加載的類就更多了。

  • 運行時常量池

    運行時常量池是方法區的一部分。Class 文件中除了有類的版本、字段、方法、接口等描述信息外,還有常量池信息(用于存放編譯期生成的各種字面量和符號引用)

    既然運行時常量池是方法區的一部分,自然受到方法區內存的限制,當常量池無法再申請到內存時會拋出 OutOfMemoryError 錯誤。

    **JDK1.7 及之后版本的 JVM 已經將字符串常量池從方法區中移了出來,在 Java 堆(Heap)中開辟了一塊區域存放字符串常量池。**但是運行時常量池的其他內容還在方法區,也就是在元空間里面。

    直接內存

    直接內存并不是虛擬機運行時數據區的一部分,也不是虛擬機規范中定義的內存區域,但是這部分內存也被頻繁地使用。而且也可能導致 OutOfMemoryError 錯誤出現。

    JDK1.4 中新加入的 NIO(New Input/Output) 類,引入了一種基于通道(Channel)緩存區(Buffer) 的 I/O 方式,它可以直接使用 Native 函數庫直接分配堆外內存,然后通過一個存儲在 Java 堆中的 DirectByteBuffer 對象作為這塊內存的引用進行操作。這樣就能在一些場景中顯著提高性能,因為避免了在 Java 堆和 Native 堆之間來回復制數據。

    本機直接內存的分配不會受到 Java 堆的限制,但是,既然是內存就會受到本機總內存大小以及處理器尋址空間的限制。

    HotSpot虛擬機對象探秘

    對象的創建

    通過上面的介紹我們大概知道了虛擬機的內存情況,下面我們來詳細的了解一下 HotSpot 虛擬機在 Java 堆中對象分配、布局和訪問的全過程。

    Step1:類加載檢查

    虛擬機遇到一條 new 指令時,首先將去檢查這個指令的參數是否能在常量池中定位到這個類的符號引用,并且檢查這個符號引用代表的類是否已被加載過、解析和初始化過。如果沒有,那必須先執行相應的類加載過程。

    Step2:分配內存

    類加載檢查通過后,接下來虛擬機將為新生對象分配內存。對象所需的內存大小在類加載完成后便可確定,為對象分配空間的任務等同于把一塊確定大小的內存從 Java 堆中劃分出來。分配方式“指針碰撞”“空閑列表” 兩種,選擇那種分配方式由 Java 堆是否規整決定,而 Java 堆是否規整又由所采用的垃圾收集器是否帶有壓縮整理功能決定

    內存分配的兩種方式

    選擇以上兩種方式中的哪一種,取決于 Java 堆內存是否規整。而 Java 堆內存是否規整,取決于 GC 收集器的算法是"標記-清除",還是"標記-整理"(也稱作"標記-壓縮"),值得注意的是,復制算法內存也是規整的。

    內存分配并發問題

    在創建對象的時候有一個很重要的問題,就是線程安全,因為在實際開發過程中,創建對象是很頻繁的事情,作為虛擬機來說,必須要保證線程是安全的,通常來講,虛擬機采用兩種方式來保證線程安全:

    • CAS+失敗重試: CAS 是樂觀鎖的一種實現方式。所謂樂觀鎖就是,每次不加鎖而是假設沒有沖突而去完成某項操作,如果因為沖突失敗就重試,直到成功為止。虛擬機采用 CAS 配上失敗重試的方式保證更新操作的原子性。
    • **本地線程分配緩沖(TLAB):**為每一個線程預先在 Eden 區分配一塊兒內存,稱為TLAB;JVM 在給線程中的對象分配內存時,首先在 TLAB 分配,當對象大于 TLAB 中的剩余內存或 TLAB 的內存已用盡時,再采用上述的 CAS 進行內存分配。

    Step3:初始化零值

    內存分配完成后,虛擬機需要將分配到的內存空間都初始化為零值(不包括對象頭),這一步操作保證了對象的實例字段在 Java 代碼中可以不賦初始值就直接使用,程序能訪問到這些字段的數據類型所對應的零值。

    Step4:設置對象頭

    初始化零值完成之后,虛擬機要對 對象進行必要的設置,例如這個對象是那個類的實例、如何才能找到類的元數據信息、對象的哈希碼、對象的 GC 分代年齡等信息。 這些信息存放在對象頭中。 另外,根據虛擬機當前運行狀態的不同,如是否啟用偏向鎖等,對象頭會有不同的設置方式。

    Step5:執行 init 方法

    在上面工作都完成之后,從虛擬機的視角來看,一個新的對象已經產生了,但從 Java 程序的視角來看,對象創建才剛開始。<init>方法還沒有執行,所有的字段都還為零。所以一般來說,執行 new 指令之后會接著執行<init>方法,把對象按照程序員的意愿進行初始化,這樣一個真正可用的對象才算完全產生出來。(<init>方法即初始化方法或者稱為構造方法)

    對象的內存布局

    在 Hotspot 虛擬機中,對象在內存中的布局可以分為 3 塊區域:對象頭、實例數據對齊填充。

    對象頭

    Hotspot 虛擬機的對象頭包括兩部分信息第一部分用于存儲對象自身的運行時數據,另一部分是類型指針。

    對象自身的運行時數據

    包括哈希碼、GC 分代年齡、鎖狀態標志、線程持有的鎖、偏向線程ID和偏向時間戳等,這部分數據的長度在32位和64位的虛擬機中分別為32bit和64bit,稱為**“Mark Word”**。

    對象需要存儲的運行時數據很多,其實已經超過64bit,因對象頭里的信息是與對象自身定義無關的額外存儲成本,所以Mark Word被設計成一個動態數據結構,根據對象的狀態復用自己的存儲空間。

    在32位的HotSpot虛擬機中,Mark Word存儲內容如下:

    如:在對象未被鎖時,Mark Word的25bit存儲對象的hashcode,4bit存儲分代年齡,1bit表示是否偏向鎖,2bit用于存儲鎖標志位。不用的鎖狀態用不同的鎖標志位表示。

    可以看到,分代年齡最大為15,因為只用4bit存儲。

    類型指針

    類型指針是對象指向它的類型元數據的指針,Java虛擬機通過這個指針來確定該對象是哪個類的實例。并不是所有的虛擬機實現都必須在對象數據上保留類型指針,即查找對象的元數據信息不一定要經過對象本身。

    如果對象是一個Java數組,那在對象頭上還必須有一塊用于記錄數組長度的數據,因為虛擬機可以通過普通Java對象的元數據信息確定Java對象的大小,但是如果數組的長度是不確定的,將無法通過元數據中的信息推斷出數組的大小。

    實例數據

    實例數據部分是對象真正存儲的有效信息,即我們定義的各種類型的字段內容,無論是從父類繼承下來的,還是子類中定義的,都必須記錄下來。

    HotSpot虛擬機默認的分配順序為longs/doubles、ints、shorts/chars、bytes/booleans、oops,從以上默認的分配策略中可以看到,相同寬度的字段總是被分配到一起存放,在滿足這個前提條件下,在父類中定義的變量會出現在子類之前。

    對齊填充

    對齊填充部分不是必然存在的,也沒有什么特別的含義,僅僅起占位作用。 因為 Hotspot 虛擬機的自動內存管理系統要求對象起始地址必須是 8 字節的整數倍,換句話說就是對象的大小必須是 8 字節的整數倍。而對象頭部分正好是 8 字節的倍數(1 倍或 2 倍),因此,當對象實例數據部分沒有對齊時,就需要通過對齊填充來補全。

    對象的訪問定位

    建立對象就是為了使用對象,我們的 Java 程序通過棧上的 reference 數據來操作堆上的具體對象。對象的訪問方式由虛擬機實現而定,目前主流的訪問方式有①使用句柄②直接指針兩種:

    句柄: 如果使用句柄的話,那么 Java 堆中將會劃分出一塊內存來作為句柄池,reference 中存儲的就是對象的句柄地址,而句柄中包含了對象實例數據與類型數據各自的具體地址信息;

    直接指針: 如果使用直接指針訪問,那么 Java 堆對象的布局中就必須考慮如何放置訪問類型數據的相關信息,而 reference 中存儲的直接就是對象的地址。

    這兩種對象訪問方式各有優勢。使用句柄來訪問的最大好處是 reference 中存儲的是穩定的句柄地址,在對象被移動時只會改變句柄中的實例數據指針,而 reference 本身不需要修改。使用直接指針訪問方式最大的好處就是速度快,它節省了一次指針定位的時間開銷。

    String 類和常量池

    String對象的兩種創建方式:

    String str1 = "abcd";//先檢查字符串常量池中有沒有"abcd",如果字符串常量池中沒有,則創建一個,然后 str1 指向字符串常量池中的對象,如果有,則直接將 str1 指向"abcd""; String str2 = new String("abcd");//堆中創建一個新的對象 String str3 = new String("abcd");//堆中創建一個新的對象 System.out.println(str1==str2);//false System.out.println(str2==str3);//false

    因為str1是字面量,字面量是存儲在常量池的,通過new創建的是一個對象,對象是存儲在java堆的。

    這兩種不同的創建方法是有差別的。

    • 第一種方式是在常量池中拿對象;
    • 第二種方式是直接在堆內存空間創建一個新的對象。

    記住一點:只要使用 new 方法,便需要創建新的對象。

    String 類型的常量池比較特殊。它的主要使用方法有兩種:

    • 直接使用雙引號聲明出來的 String 對象會直接存儲在常量池中。
    • 如果不是用雙引號聲明的 String 對象,可以使用 String 提供的 intern 方法。String.intern() 是一個 Native 方法,它的作用是:如果運行時常量池中已經包含一個等于此 String 對象內容的字符串,則返回常量池中該字符串的引用;如果沒有,JDK1.7之前(不包含1.7)的處理方式是在常量池中創建與此 String 內容相同的字符串(就是在常量池存儲一個副本),并返回常量池中創建的字符串的引用,JDK1.7以及之后的處理方式是在常量池中存儲此字符串的引用,并返回該引用。注意:JDK 1.6及以后存儲的是字符串的一個副本,JDK 1.7及其以后存儲的是字符串的引用,存儲內容變了。見幾張圖輕松理解String.intern()
    String s1 = new String("計算機"); String s2 = s1.intern(); String s3 = "計算機"; System.out.println(s2);//計算機 System.out.println(s1 == s2);//false,因為一個是堆內存中的 String 對象一個是常量池中的 String 對象, System.out.println(s3 == s2);//true,因為兩個都是常量池中的 String 對象

    把第二行和第三行互換順序,依然是同樣的結果。

    字符串拼接:

    String str1 = "str"; String str2 = "ing";String str3 = "str" + "ing";//常量池中的對象 String str4 = str1 + str2; //在堆上創建的新的對象 String str5 = "string";//常量池中的對象 System.out.println(str3 == str4);//false System.out.println(str3 == str5);//true System.out.println(str4 == str5);//false

    盡量避免多個字符串拼接,因為這樣會重新創建對象。如果需要改變字符串的話,可以使用 StringBuilder 或者 StringBuffer。

  • 常量字符串的“+”操作,編譯階段直接會合成為一個字符串。如string str=”JA”+”VA”,在編譯階段會直接合并成語句String str=”JAVA”,于是會去常量池中查找是否存在”JAVA”,從而進行創建或引用。

  • 對于final字段,編譯期直接進行了常量替換(而對于非final字段則是在運行期進行賦值處理的)。

    final String str1=”ja”; final String str2=”va”; String str3=str1+str2;

    在編譯時,直接替換成了String str3=”ja”+”va”,根據第三條規則,再次替換成String str3=”JAVA”

  • 常量字符串和變量拼接時(如:String str3=baseStr + “01”;)會調用stringBuilder.append()在堆上創建新的對象。

  • 小問題

    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

    8 種基本類型的包裝類和常量池

    Java 基本類型的包裝類的大部分都實現了常量池技術,即 Byte,Short,Integer,Long,Character,Boolean;前面 4 種包裝類默認創建了數值[-128,127] 的相應類型的緩存數據,Character創建了數值在[0,127]范圍的緩存數據,Boolean 直接返回True Or False。如果超出對應范圍仍然會去創建新的對象。 為啥把緩存設置為[-128,127]區間?(參見issue/461)性能和資源之間的權衡。

    public static Boolean valueOf(boolean b) {return (b ? TRUE : FALSE); }private static class CharacterCache { private CharacterCache(){}static final Character cache[] = new Character[127 + 1]; static { for (int i = 0; i < cache.length; i++) cache[i] = new Character((char)i); } }

    兩種浮點數類型的包裝類 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 緩存源代碼:

    /** *此方法將始終緩存-128 到 127(包括端點)范圍內的值,并可以緩存此范圍之外的其他值。 */ public static Integer valueOf(int i) {if (i >= IntegerCache.low && i <= IntegerCache.high)return IntegerCache.cache[i + (-IntegerCache.low)];return new Integer(i); }

    應用場景:

  • 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 比較更豐富的一個例子:

    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 System.out.println("40=i5+i6 " + (40 == i5 + i6)); // true

    解釋:

    語句 i4 == i5 + i6,因為+這個操作符不適用于 Integer 對象,首先 i5 和 i6 進行自動拆箱操作,進行數值相加,即 i4 == 40。然后 Integer 對象無法與數值進行直接比較,所以 i4 自動拆箱轉為 int 值 40,最終這條語句轉為 40 == 40 進行數值比較。

    參考鏈接

    • 《深入理解 Java 虛擬機:JVM 高級特性與最佳實踐(第三版》
    • Guide哥的筆記
    • 幾張圖輕松理解String.intern()

    垃圾收集器與內存分配策略

    本章常見面試題

    • 如何判斷對象是否死亡(兩種方法)。
    • 簡單的介紹一下強引用、軟引用、弱引用、虛引用(虛引用與軟引用和弱引用的區別、使用軟引用能帶來的好處)。
    • 如何判斷一個常量是廢棄常量
    • 如何判斷一個類是無用的類
    • 垃圾收集有哪些算法,各自的特點?
    • HotSpot 為什么要分為新生代和老年代?
    • 常見的垃圾回收器有哪些?
    • 介紹一下 CMS,G1 收集器。
    • Minor Gc 和 Full GC 有什么不同呢?

    導論

    當需要排查各種內存溢出問題、當垃圾收集成為系統達到更高并發的瓶頸時,我們就需要對這些“自動化”的技術實施必要的監控和調節。

    概述

    Java內存區域中程序計數器、虛擬機棧、本地方法棧3個區域隨著線程而生,隨著線程而滅。每一個棧幀中分配多少內存基本上是在類結構確定下來就已知的,這幾個區域的內存分配和回收都具備確定性,不需要過多考慮回收的問題,當方法結束或者線程結束時,內存自然就跟著回收了。

    Java堆和方法區這兩個內存區域則有很顯著的不確定性,一個接口的多個實現類需要的內存可能會不一樣,一個方法所執行的不同條件分支所需要的內存也可能不一樣,只有處于運行期間,我們才能知道程序究竟會創建哪些對象,創建多少個對象,這部分內存分配和回收是動態的。垃圾收集器正是關注這部分內存。

    JVM內存分配和回收基礎

    Java 的自動內存管理主要是針對對象內存的回收和對象內存的分配。同時,Java 自動內存管理最核心的功能是 內存中對象的分配與回收。

    Java 堆是垃圾收集器管理的主要區域,因此也被稱作GC 堆(Garbage Collected Heap).從垃圾回收的角度,由于現在收集器基本都采用分代垃圾收集算法,所以 Java 堆還可以細分為:新生代和老年代:再細致一點有:Eden 空間、From Survivor、To Survivor 空間等。進一步劃分的目的是更好地回收內存,或者更快地分配內存。

    一些術語:

    • 部分收集(Partial GC):指目標不是完整收集整個Java堆的垃圾,而且對部分區域收集??杉毞譃?#xff1a;
      • 新生代收集(Minor GC/Young GC)
      • 老年代收集(Major GC/Old GC)
      • 混合收集(Mixed GC):收集整個新生代以及部分老年代
    • 整堆收集(Full GC):收集整個Java堆和方法區的垃圾

    堆空間的基本結構:

    上圖所示的 eden 區、s0(“From”) 區、s1(“To”) 區都屬于新生代,tentired 區屬于老年代。大部分情況,對象都會首先在 Eden 區域分配,在一次新生代垃圾回收后,如果對象還存活,則會進入 s1(“To”),并且對象的年齡還會加 1(Eden 區->Survivor 區后對象的初始年齡變為 1),當它的年齡增加到一定程度(默認為 15 歲),就會被晉升到老年代中。對象晉升到老年代的年齡閾值,可以通過參數 -XX:MaxTenuringThreshold 來設置。經過這次GC后,Eden區和"From"區已經被清空。這個時候,“From"和"To"會交換他們的角色,也就是新的"To"就是上次GC前的“From”,新的"From"就是上次GC前的"To”。不管怎樣,都會保證名為To的Survivor區域是空的。Minor GC會一直重復這樣的過程,直到“To”區被填滿,"To"區被填滿之后,會將所有對象移動到老年代中。

    對象優先在 eden 區分配

    目前主流的垃圾收集器都會采用分代回收算法,因此需要將堆內存分為新生代和老年代,這樣我們就可以根據各個年代的特點選擇合適的垃圾收集算法。

    大多數情況下,對象在新生代中 eden 區分配。當 eden 區沒有足夠空間進行分配時,虛擬機將發起一次 Minor GC,如果當Minor GC后eden區依然沒有足夠的空間進行分配,只好通過分配擔保機制 把新生代的對象提前轉移到老年代中去;如果執行分配擔保機制后eden區依然存不下該對象,則再老年代分配;如果能存在,則繼續在eden區分配。

    Minor GC 和 Full GC 有什么不同呢?

    • 新生代 GC(Minor GC):指發生新生代的的垃圾收集動作,Minor GC 非常頻繁,回收速度一般也比較快。
    • 老年代 GC(Major GC):指發生在老年代的 GC,出現了 Major GC 經常會伴隨至少一次的 Minor GC(并非絕對),Major GC 的速度一般會比 Minor GC 的慢 10 倍以上。

    大對象直接進入老年代

    大對象就是需要大量連續內存空間的對象(比如:字符串、數組)。

    為什么要這樣呢?

    為了避免為大對象分配內存時由于分配擔保機制帶來的復制而降低效率。

    長期存活的對象將進入老年代

    既然虛擬機采用了分代收集的思想來管理內存,那么內存回收時就必須能識別哪些對象應放在新生代,哪些對象應放在老年代中。為了做到這一點,虛擬機給每個對象一個對象年齡(Age)計數器。

    如果對象在 Eden 出生并經過第一次 Minor GC 后仍然能夠存活,并且能被 Survivor 容納的話,將被移動到 Survivor 空間中,并將對象年齡設為 1.對象在 Survivor 中每熬過一次 MinorGC,年齡就增加 1 歲,當它的年齡增加到一定程度(默認為 15 歲),就會被晉升到老年代中。對象晉升到老年代的年齡閾值,可以通過參數 -XX:MaxTenuringThreshold 來設置。

    動態對象年齡判定

    虛擬機并不是永遠要求對象的年齡必須達到 MaxTenuringThreshold 才能晉升老年代,如果在 Survivor 中相同年齡所有對象大小的總和大于 Survivor 空間的一半,則年齡大于或等于該年齡的對象可以直接進入老年代,無需等到 MaxTenuringThreshold 中要求的年齡。

    空間分配擔保

    在發生 Minor GC 之前,虛擬機先檢查老年代最大可用的連續空間是否大于新生代所有對象總空間,如果條件成立的話,那么 Minor GC 可以確認是安全的。

    如果不成立的話虛擬機會查看 HandlePromotionFailure 的值是否允許擔保失敗,如果允許那么就會繼續檢查老年代最大可用的連續空間是否大于歷次晉升到老年代對象的平均大小,如果大于,將嘗試著進行一次 Minor GC;如果小于,或者 HandlePromotionFailure 的值不允許冒險,那么就要進行一次 Full GC。

    Full GC 的觸發條件

    對于 Minor GC,其觸發條件非常簡單,當 Eden 空間滿時,就將觸發一次 Minor GC。而 Full GC 則相對復雜,有以下條件:

    1. 調用 System.gc()

    只是建議虛擬機執行 Full GC,但是虛擬機不一定真正去執行。不建議使用這種方式,而是讓虛擬機管理內存。

    2. 老年代空間不足

    老年代空間不足的常見場景為前文所講的大對象直接進入老年代、長期存活的對象進入老年代等。

    為了避免以上原因引起的 Full GC,應當盡量不要創建過大的對象以及數組。除此之外,可以通過 -Xmn 虛擬機參數調大新生代的大小,讓對象盡量在新生代被回收掉,不進入老年代。還可以通過 -XX:MaxTenuringThreshold 調大對象進入老年代的年齡,讓對象在新生代多存活一段時間。

    3. 空間分配擔保失敗

    使用復制算法的 Minor GC 需要老年代的內存空間作擔保,如果擔保失敗會執行一次 Full GC。具體內容請參考上面的內容。

    4. JDK 1.7 及以前的永久代空間不足

    在 JDK 1.7 及以前,HotSpot 虛擬機中的方法區是用永久代實現的,永久代中存放的為一些 Class 的信息、常量、靜態變量等數據。

    當系統中要加載的類、反射的類和調用的方法較多時,永久代可能會被占滿,在未配置為采用 CMS GC 的情況下也會執行 Full GC。如果經過 Full GC 仍然回收不了,那么虛擬機會拋出 java.lang.OutOfMemoryError。

    為避免以上原因引起的 Full GC,可采用的方法為增大永久代空間或轉為使用 CMS GC。

    5. Concurrent Mode Failure

    執行 CMS GC 的過程中同時有對象要放入老年代,而此時老年代空間不足(可能是 GC 過程中浮動垃圾過多導致暫時性的空間不足),便會報 Concurrent Mode Failure 錯誤,并觸發 Full GC。

    對象已死?

    堆中幾乎放著所有的對象實例,對堆垃圾回收前的第一步就是要判斷那些對象已經死亡(即不能再被任何途徑使用的對象)。

    下面介紹判斷一個對象是否死亡的兩種方法。

    引用計數法

    給對象中添加一個引用計數器,每當有一個地方引用它,計數器就加 1;當引用失效,計數器就減 1;任何時候計數器為 0 的對象就是不可能再被使用的。

    這個方法實現簡單,效率高,但是目前主流的虛擬機中并沒有選擇這個算法來管理內存,其最主要的原因是它很難解決對象之間相互循環引用的問題。 所謂對象之間的相互引用問題,如下面代碼所示:除了對象 objA 和 objB 相互引用著對方之外,這兩個對象之間再無任何引用。但是他們因為互相引用對方,導致它們的引用計數器都不為 0,于是引用計數算法無法通知 GC 回收器回收他們。

    public class ReferenceCountingGc {Object instance = null;public static void main(String[] args) {ReferenceCountingGc objA = new ReferenceCountingGc();ReferenceCountingGc objB = new ReferenceCountingGc();objA.instance = objB;objB.instance = objA;objA = null;objB = null;} }

    可達性分析算法

    這個算法的基本思想就是通過一系列的稱為 “GC Roots” 的對象作為起點,從這些節點開始向下搜索,節點所走過的路徑稱為引用鏈,當一個對象到 GC Roots 沒有任何引用鏈相連的話,則證明此對象是不可用的。

    GC Roots

    在Java技術體系中,固定可作為GC Roots的對象包括以下幾種:

    • 在虛擬機棧中引用的對象,比如各個線程被調用的方法堆棧中使用到的參數、局部變量、臨時變量等。
    • 在方法區中類靜態屬性引用的對象,比如Java類的引用類型靜態變量。
    • 在方法區中常量引用的對象,比如字符串常量池里的引用。
    • 在本地方法棧中JNI(即通常所說的Native方法)引用的對象。
    • Java虛擬機內部的引用,如基本類型對應的Class對象,一些常駐的異常對象(比如NullPointException)等,還有系統類加載器。
    • 所有被同步鎖(synchronized關鍵字)所持有的對象。

    再談引用

    無論是通過引用計數法判斷對象引用數量,還是通過可達性分析法判斷對象的引用鏈是否可達,判定對象的存活都與“引用”有關。

    JDK1.2 之前,Java 中引用的定義很傳統:如果 reference 類型的數據存儲的數值代表的是另一塊內存的起始地址,就稱這塊內存代表一個引用。

    JDK1.2 以后,Java 對引用的概念進行了擴充,將引用分為強引用、軟引用、弱引用、虛引用四種(引用強度逐漸減弱)。

    強引用

    以前我們使用的大部分引用實際上都是強引用,這是使用最普遍的引用。如果一個對象具有強引用,那就類似于必不可少的生活用品,垃圾回收器絕不會回收它。當內存空間不足,Java 虛擬機寧愿拋出 OutOfMemoryError 錯誤,使程序異常終止,也不會靠隨意回收具有強引用的對象來解決內存不足問題。

    軟引用

    如果一個對象只具有軟引用,那就類似于可有可無的生活用品。如果內存空間足夠,垃圾回收器就不會回收它,如果內存空間不足了,就會回收這些對象的內存。只要垃圾回收器沒有回收它,該對象就可以被程序使用。軟引用可用來實現內存敏感的高速緩存。

    軟引用可以和一個引用隊列(ReferenceQueue)聯合使用,如果軟引用所引用的對象被垃圾回收,JAVA 虛擬機就會把這個軟引用加入到與之關聯的引用隊列中。

    弱引用

    如果一個對象只具有弱引用,那就類似于可有可無的生活用品。弱引用與軟引用的區別在于:只具有弱引用的對象擁有更短暫的生命周期。在垃圾回收器線程掃描它所管轄的內存區域的過程中,一旦發現了只具有弱引用的對象,不管當前內存空間足夠與否,都會回收它的內存。不過,由于垃圾回收器是一個優先級很低的線程, 因此不一定會很快發現那些只具有弱引用的對象。

    弱引用可以和一個引用隊列(ReferenceQueue)聯合使用,如果弱引用所引用的對象被垃圾回收,Java 虛擬機就會把這個弱引用加入到與之關聯的引用隊列中。

    應用

    假如一個應用需要讀取大量的本地圖片,如果每次讀取圖片都從硬盤讀取則會嚴重影響性能,如果一次性全部加裝到內存中又可能造成內存溢出。這時可以用軟引用或者弱引用解決這個問題。

    Map<String, SoftReference<Bitmap>> imageCache = new HashMap<String, SoftReference<Bitmap>>();
    WeakHashMap
    import java.util.WeakHashMap;/*** @author wardseptember* @create 2020-09-23 13:39*/ public class WeakHashMapDemo {public static void main(String[] args) {myWeakHashMap();}private static void myWeakHashMap() {WeakHashMap<Integer, String> map = new WeakHashMap<>();Integer key = new Integer(1);String value = "https://wardseptember.gitee.io";map.put(key, value);System.out.println(map);key = null;// 手動觸發一次GCSystem.gc();System.out.println(map);} }
    ReferenceQueue
    import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference;/*** @author wardseptember* @create 2020-09-23 13:50*/ public class WeakReferenceDemo {public static void main(String[] args) {Object o1 = new Object();ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();WeakReference<Object> weakReference = new WeakReference<>(o1, referenceQueue);System.out.println(o1);System.out.println(weakReference.get());System.out.println(referenceQueue.poll());System.out.println("==============");o1 = null;System.gc();try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}// o1被回收前,會給referenceQueue發送一個通知System.out.println(o1);System.out.println(weakReference.get());System.out.println(referenceQueue.poll());} }

    虛引用

    "虛引用"顧名思義,就是形同虛設,與其他幾種引用都不同,虛引用并不會決定對象的生命周期。如果一個對象僅持有虛引用,那么它就和沒有任何引用一樣,在任何時候都可能被垃圾回收。

    虛引用主要用來跟蹤對象被垃圾回收的活動。

    為一個對象設置虛引用關聯的唯一目的只是為了能在這個對象被收集器回收時收到一個系統通知。

    虛引用與軟引用和弱引用的一個區別在于: 虛引用必須和引用隊列(ReferenceQueue)聯合使用。當垃圾回收器準備回收一個對象時,如果發現它還有虛引用,就會在回收對象的內存之前,把這個虛引用加入到與之關聯的引用隊列中。程序可以通過判斷引用隊列中是否已經加入了虛引用,來了解被引用的對象是否將要被垃圾回收。程序如果發現某個虛引用已經被加入到引用隊列,那么就可以在所引用的對象的內存被回收之前采取必要的行動。

    PhantomReference的get方法總是返回null。

    特別注意,在程序設計中一般很少使用弱引用與虛引用,使用軟引用的情況較多,這是因為軟引用可以加速 JVM 對垃圾內存的回收速度,可以維護系統的運行安全,防止內存溢出(OutOfMemory)等問題的產生

    PhantomReference
    import java.lang.ref.PhantomReference; import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference;/*** @author wardseptember* @create 2020-09-23 13:50*/ public class PhantomReferenceDemo {public static void main(String[] args) {Object o1 = new Object();ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();PhantomReference<Object> phantomReference = new PhantomReference<>(o1, referenceQueue);System.out.println(o1);System.out.println(phantomReference.get());System.out.println(referenceQueue.poll());System.out.println("==============");o1 = null;System.gc();try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}// o1被回收前,會給referenceQueue發送一個通知System.out.println(o1);System.out.println(phantomReference.get());System.out.println(referenceQueue.poll());} }

    生存還是死亡?

    即使在可達性分析法中不可達的對象,也并非是“非死不可”的,這時候它們暫時處于“緩刑階段”,要真正宣告一個對象死亡,至少要經歷兩次標記過程;如果對象在進行可達性分析后被判斷為不可達對象,那它將會被第一次標記,隨后進行一次篩選,篩選的條件是此對象是否有必要執行finalize()方法。對象沒有覆蓋 finalize 方法,或 finalize 方法已經被虛擬機調用過時,虛擬機將這兩種情況視為沒有必要執行。

    被判定為需要執行finalize()方法的對象將會被放在一個隊列中進行第二次標記,除非這個對象與引用鏈上的任何一個對象建立關聯,否則就會被真的回收。finalize()方法是對象逃脫回收的最后一次機會。自救只能進行一次,如果回收的對象之前調用了 finalize() 方法自救,后面回收時不會再調用該方法。

    finalize()類似 C++ 的析構函數,用于關閉外部資源。但是 try-finally 等方式可以做得更好,并且該方法運行代價很高,不確定性大,無法保證各個對象的調用順序,因此最好不要使用。

    回收方法區

    方法區的垃圾收集主要回收廢棄的常量和不再使用的類型。

    如何判斷一個常量是廢棄常量

    假如在常量池中存在數值“333” ,如果當前沒有任何 int 引用該常量的話,就說明常量 “333" 就是廢棄常量,如果這時發生內存回收的話而且有必要的話,”333" 就會被系統清理出常量池。

    如何判斷一個類是無用的類

    • 該類所有的實例都已經被回收,也就是 Java 堆中不存在該類及其任何派生子類的實例。
    • 加載該類的 ClassLoader 已經被回收。
    • 該類對應的 java.lang.Class 對象沒有在任何地方被引用,無法在任何地方通過反射訪問該類的方法。

    虛擬機可以對滿足上述 3 個條件的無用類進行回收,這里說的僅僅是“可以”,而并不是和對象一樣不使用了就會必然被回收。

    OOM

    Java.lang.StackOverflowError

    棧溢出,棧里面存儲的是方法的調用,上面有講。

    Java.lang.OutOfMemoryError: Java heap space

    對象太多,堆溢出。

    Java.lang.OutOfMemoryError: GC overhead limit exceeded

    GC回收時間過長時會拋出OutOfMemroyError。過長的定義是,超過98%的時間用來做GC并且回收了不到2%的堆內存,連續多次GC都只回收了不到2%的內存的極端情況下才會拋出。CPU使用率一直是100%,而GC卻沒有任何成果。

    Java.lang.OutOfMemoryError: Direct buffer memory

    ByteBuffer.allocateDirect(capability)分配操作系統本地內存,不屬于GC管轄范圍。分配太多,可能導致 Direct buffer memory

    Java.lang.OutOfMemoryError: unable to create new native thread

    創建太多線程。

    導致原因

    • 一個應用進程創建了多個線程,超過系統承載極限。
    • 服務器不允許你的應該程序創建這么多線程,linux系統默認允許單個進程可以創建的線程數是1024個。

    解決辦法

    • 想辦法降低你應用程序創建線程的數量,分析應用是否真的需要創建這么多線程,如果不是,改代碼將線程數降到最低。
    • 對于有的應用,確實需要創建很多線程,遠超過linux系統的默認1024個線程的限制,可以通過修改linux服務器配置,擴大linux默認限制

    Java.lang.OutOfMemoryError: Metaspace

    Metaspace是方法區在HotSpot中的實現,使用的是本地內存,主要存儲虛擬機加載的類信息、常量池、靜態變量、即時編譯后的代碼等。

    如果類太多,就報Java.lang.OutOfMemoryError: Metaspace.

    垃圾收集算法

    從如何判定對象消亡的角度出發,垃圾收集算法可以劃分為“引用計數式垃圾收集”和“追蹤式垃圾收集“。本文全部屬于追蹤式垃圾收集范疇。

    分代收集理論

    當前虛擬機的垃圾收集都采用分代收集算法,這種算法沒有什么新的思想,只是根據對象存活周期的不同將內存分為幾塊。一般將 java 堆分為新生代和老年代,這樣我們就可以根據各個年代的特點選擇合適的垃圾收集算法。

    比如在新生代中,每次收集都會有大量對象死去,所以可以選擇復制算法,只需要付出少量對象的復制成本就可以完成每次垃圾收集。而老年代的對象存活幾率是比較高的,而且沒有額外的空間對它進行分配擔保,所以我們必須選擇“標記-清除”或“標記-整理”算法進行垃圾收集。

    標記-清除算法

    該算法分為“標記”和“清除”階段:首先標記出所有需要回收的對象,在標記完成后統一回收所有被標記的對象。它是最基礎的收集算法,后續的算法都是對其不足進行改進得到。這種垃圾收集算法會帶來兩個明顯的問題:

    • 執行效率不穩定。如果Java堆中包含大量需要被回收的對象,這是必須進行大量的標記和清除動作,導致回收效率降低。
    • 內存空間碎片化。標記、清除之后會產生大量不連續的內存碎片,空間碎片太多可能會導致當以后程序運行過程中需要分配較大對象時無法找到足夠的連續內存而不得不提前觸發另一次垃圾收集動作。

    標記-復制算法

    為了解決標記-清除算法中的效率問題,“復制”收集算法出現了。它可以將內存分為大小相同的兩塊,每次使用其中的一塊。當這一塊的內存使用完后,就將還存活的對象復制到另一塊去,然后再把使用的空間一次清理掉。這樣就使每次的內存回收都是對內存區間的一半進行回收。

    缺點:

    • 可用內存縮小為原來的一半,空間浪費明顯。
    • 當對象存活率高時,復制效率低。

    標記-整理算法

    根據老年代的特點提出的一種標記算法,標記過程仍然與“標記-清除”算法一樣,但后續步驟不是直接對可回收對象回收,而是讓所有存活的對象向一端移動,然后直接清理掉端邊界以外的內存。

    缺點:

    • 如果移動存活對象,尤其是在老年代這種每次回收都有大量對象存活區域,這種移動操作必須全程暫停用戶應用程序才能進行。

    HotSpot的算法細節實現

    此節暫時省略。

    經典垃圾收集器

    1.新生代的收集器包括

    Serial
    PraNew
    Parallel Scavenge

    2.老年代的收集器包括

    Serial Old
    Parallel Old
    CMS

    3.回收整個Java堆(新生代和老年代)

    G1收集器

    以上是 HotSpot 虛擬機中的 7 個垃圾收集器,連線表示垃圾收集器可以配合使用;圖中收集器所處的區域,則表示它是屬于新生代收集器或者是老年代收集器。

    • 單線程與多線程:單線程指的是垃圾收集器只使用一個線程,而多線程使用多個線程;
    • 串行與并行:串行指的是垃圾收集器與用戶程序交替執行,這意味著在執行垃圾收集的時候需要停頓用戶程序;并行指的是垃圾收集器和用戶程序同時執行。除了 CMS 和 G1 之外,其它垃圾收集器都是以串行的方式執行。

    Serial 收集器 Serial串行收集器-復制算法

    Serial(串行)收集器收集器是最基本、歷史最悠久的垃圾收集器了。大家看名字就知道這個收集器是一個單線程收集器了。它的 “單線程” 的意義不僅僅意味著它只會使用一條垃圾收集線程去完成垃圾收集工作,更重要的是它在進行垃圾收集工作的時候必須暫停其他所有的工作線程( “Stop The World” ),直到它收集結束。

    總結

    Serial有如下特點:

    針對新生代;
    采用復制算法;
    單線程收集;
    進行垃圾收集時,必須暫停所有工作線程,直到完成;

    優勢:

    簡單高效,由于采用的是單線程的方法,因此與其他類型的收集器相比,對單個cpu來說沒有了上下文之間的的切換,效率比較高。

    劣勢:

    會在用戶不知道的情況下停止所有工作線程。

    使用場景

    Client 模式(桌面應用)
    在用戶的桌面應用場景中,可用內存一般不大,可以在較短時間內完成垃圾收集,只要不頻繁發生,這是可以接受的

    單核服務器
    對于限定單個CPU的環境來說,Serial收集器沒有線程切換開銷,可以獲得最高的單線程收集效率

    參數設置
    -XX:+UseSerialGC:添加該參數來顯式的使用串行垃圾收集器

    新生代采用復制算法,老年代采用標記-整理算法。

    它的優點是簡單高效,在單個 CPU 環境下,由于沒有線程交互的開銷,因此擁有最高的單線程收集效率。

    它是 Client 場景下的默認新生代收集器,因為在該場景下內存一般來說不會很大。它收集一兩百兆垃圾的停頓時間可以控制在一百多毫秒以內,只要不是太頻繁,這點停頓時間是可以接受的。

    ParNew 收集器 復制算法

    它是 Serial 收集器的多線程版本。

    它是 Server 場景下默認的新生代收集器,除了性能原因外,主要是因為除了 Serial 收集器,只有它能與 CMS 收集器配合使用。

    自JDK 9開始,ParNew加CMS收集器的組合就不再是官方推薦的服務端模式下的收集器解決方案,官方希望G1(Garbage First)能完全取代它。

    并行和并發概念補充:

    • 并行(Parallel) :并行描述的是多條垃圾收集器線程之間的關系,指同一時間多條垃圾收集線程在協同工作,但此時用戶線程仍然處于等待狀態。
    • 并發(Concurrent):指用戶線程與垃圾收集線程同時執行(但不一定是并行,可能會交替執行),用戶程序在繼續運行,而垃圾收集器運行在另一個 CPU 上。

    小結

    優勢:

    多線程版本的Serial,可以更加有效的利用系統資源

    劣勢:

    同Serial,會在用戶不知道的情況下停止所有工作線程

    使用場景

    Server模式下使用,亮點是除Serial外,目前只有它能與CMS收集器配合工作,是一個非常重要的垃圾回收器。

    參數設置
    -XX:+UseConcMarkSweepGC:指定使用CMS后,會默認使用ParNew作為新生代收集器;
    -XX:+UseParNewGC:強制指定使用ParNew;
    -XX:ParallelGCThreads:指定垃圾收集的線程數量,ParNew默認開啟的收集線程與CPU的數量相同;

    Parallel Scavenge 收集器 (并行回收)收集器-復制算法

    Parallel Scavenge 收集器也是使用復制算法的多線程收集器,它看上去幾乎和ParNew都一樣。 那么它有什么特別之處呢?

    -XX:+UseParallelGC 使用 Parallel 收集器+ 老年代串行-XX:+UseParallelOldGC使用 Parallel 收集器+ 老年代并行

    CMS 等垃圾收集器的目標是盡可能縮短垃圾收集時用戶線程的停頓時間,而Parallel Scavenge的目標是達到一個可控制的吞吐量,因此它被稱為“吞吐量優先”收集器。這里的吞吐量指 CPU 用于運行用戶程序的時間占總時間的比值。

    停頓時間越短就越適合需要與用戶交互的程序,良好的響應速度能提升用戶體驗。而高吞吐量則可以高效率地利用 CPU 時間,盡快完成程序的運算任務,適合在后臺運算而不需要太多交互的任務。

    縮短停頓時間是以犧牲吞吐量和新生代空間來換取的:新生代空間變小,垃圾回收變得頻繁,導致吞吐量下降。

    可以通過一個開關參數打開 GC 自適應的調節策略(GC Ergonomics),就不需要手工指定新生代的大小(-Xmn)、Eden 和 Survivor 區的比例、晉升老年代對象年齡等細節參數了。虛擬機會根據當前系統的運行情況收集性能監控信息,動態調整這些參數以提供最合適的停頓時間或者最大的吞吐量。

    Parallel Scavenge 收集器提供了很多參數供用戶找到最合適的停頓時間或最大吞吐量,如果對于收集器運作不太了解的話,手工優化存在困難的話可以選擇把內存管理優化交給虛擬機去完成也是一個不錯的選擇。

    小結

    有如下特點:

    新生代收集器;
    采用復制算法;
    多線程收集;
    關注點與其他收集器不同:
    CMS等收集器的關注點是盡可能地縮短垃圾收集時用戶線程的停頓時間;
    而Parallel Scavenge收集器的目標則是達一個可控制的吞吐量;

    優勢:

    追求高吞吐量,高效利用CPU,是吞吐量優先,且能進行精確控制。

    劣勢:

    應該說是特點,追求高吞吐量必然要犧牲一些其他方面的優勢,不能做到既,又。ParNew收集器關注點在于盡可能的縮短垃圾收集時用戶線程的停頓時間,原本10s收集一次, 每次停頓100ms, 設置完參數之后可能變成5s收集一次, 每次停頓70ms. 停頓時間變短, 但收集次數變多。

    使用場景

    根據相關特性,我們很容易想到它的使用場景,即:當應用程序運行在具有多個CPU上,對暫停時間沒有特別高的要求時,程序主要在后臺進行計算,而不需要與用戶進行太多交互等就特別適合ParNew收集器。

    例如,那些執行批量處理、訂單處理、工資支付、科學計算的應用程序等
    參數設置
    -XX:MaxGCPauseMillis:控制最大垃圾收集停頓時間,大于0的毫秒數;
    -XX:GCTimeRatio:設置垃圾收集時間占總時間的比率,0<n<100的整數;

    Serial Old 收集器 標記整理算法

    Serial Old收集器是Serial 收集器的老年代版本,它同樣是一個單線程收集器。它主要有兩大用途:一種用途是在 JDK1.5 以及以前的版本中與 Parallel Scavenge 收集器搭配使用,另一種用途是作為 CMS 收集器發生失敗時的后備方案。

    小結

    特點

    Serial Old是Serial收集器的老年代版本,同樣是一個單線程收集器,使用標記-整理算法。

    有如下特點:

    針對老年代;
    采用"標記-整理"算法(還有壓縮,Mark-Sweep-Compact);
    單線程收集;
    優劣勢基本和Serial無異,它是和Serial收集器配合使用的老年代收集器。

    使用場景

    Client模式;
    單核服務器;
    與Parallel Scavenge收集器搭配;
    作為CMS收集器的后備方案,在并發收集發生Concurrent Mode Failure時使用

    Parallel Old收集器 收集器-標記整理算法

    Parallel Scavenge 收集器的老年代版本。使用多線程和“標記-整理”算法。在注重吞吐量以及 CPU 資源的場合,都可以優先考慮 Parallel Scavenge 收集器和 Parallel Old 收集器。

    特點:

    針對老年代;
    采用"標記-整理"算法;
    多線程收集;
    優劣勢參考Parallel Scavenge收集器。

    使用場景
    JDK1.6及之后用來代替老年代的Serial Old收集器;
    特別是在Server模式,多CPU的情況下;
    這樣在注重吞吐量以及CPU資源敏感的場景,就有了Parallel Scavenge(新生代)加Parallel Old(老年代)收集器的"給力"應用組合;

    參數設置
    -XX:+UseParallelOldGC:指定使用Parallel Old收集器

    CMS 收集器 標記整理算法

    CMS(Concurrent Mark Sweep)收集器是一種以獲取最短回收停頓時間為目標的收集器。它非常符合在注重用戶體驗的應用上使用。

    CMS(Concurrent Mark Sweep)收集器是 HotSpot 虛擬機第一款真正意義上的并發收集器,它第一次實現了讓垃圾收集線程與用戶線程(基本上)同時工作。

    從名字中的Mark Sweep這兩個詞可以看出,CMS 收集器是一種 “標記-清除”算法實現的,它的運作過程相比于前面幾種垃圾收集器來說更加復雜一些。整個過程分為四個步驟:

    • 初始標記: 暫停所有的其他線程,并記錄下直接與 root 相連的對象,速度很快 ;
    • 并發標記: 進行 GC Roots Tracing 的過程,它在整個回收過程中耗時最長,不需要停頓。
    • 重新標記: 重新標記階段就是為了修正并發標記期間因為用戶程序繼續運行而導致標記產生變動的那一部分對象的標記記錄,這個階段的停頓時間一般會比初始標記階段的時間稍長,遠遠比并發標記階段時間短
    • 并發清除: 開啟用戶線程,同時 GC 線程開始對未標記的區域做清掃

    從它的名字就可以看出它是一款優秀的垃圾收集器,主要優點:并發收集、低停頓。但是它有下面三個明顯的缺點:

    • 吞吐量低:低停頓時間是以犧牲吞吐量為代價的,導致 CPU 利用率不夠高。它會因為占用一部分線程而導致應用程序變慢,降低總吞吐量。
    • **無法處理浮動垃圾;**浮動垃圾是指并發標記和并發清除階段,由于用戶線程繼續運行而產生的垃圾,這部分垃圾只能到下一次 GC 時才能進行回收。由于用戶線程還在繼續運行,因此需要預留出一部分內存提供給用戶線程使用,意味著 CMS 收集不能像其它收集器那樣等待老年代快滿的時候再回收。如果預留的內存無法滿足程序分配新對象的需要,就會出現 一次“并發失敗”(Concurrent Mode Failure),這時虛擬機將臨時啟用 Serial Old 來替代 CMS收集老年代的垃圾。
    • **它使用的回收算法-“標記-清除”算法會導致收集結束時會有大量空間碎片產生。**往往出現老年代空間有剩余,但無法找到足夠大連續空間來分配當前對象,不得不提前觸發一次 Full GC。

    小結

    特點:

    針對老年代;
    基于"標記-清除"算法(不進行壓縮操作,產生內存碎片);
    以獲取最短回收停頓時間為目標;
    并發收集、低停頓;
    需要更多的內存(看后面的缺點);

    優勢:

    停頓時間短;
    吞吐量大;
    并發收集

    劣勢:

    對CPU資源非常敏感
    無法收集浮動垃圾
    容易產生大量內存碎片
    使用場景
    與用戶交互較多的場景;
    希望系統停頓時間最短,注重服務的響應速度;
    以給用戶帶來較好的體驗;
    如常見WEB、B/S系統的服務器上的應用。

    參數設置
    -XX:+UseConcMarkSweepGC:指定使用CMS收集器

    G1 收集器

    1.G1收集器-標記整理算法

    JDK1.7后全新的回收器, 用于取代CMS收集器。

    G1 (Garbage-First) 是一款面向服務器的垃圾收集器,主要針對配備多顆處理器及大容量內存的機器. 以極高概率滿足 GC 停頓時間要求的同時,還具備高吞吐量性能特征.

    堆被分為新生代和老年代,其它收集器進行收集的范圍都是整個新生代或者老年代,而 G1 可以直接對新生代和老年代一起回收。

    G1 把堆劃分成多個大小相等的獨立區域(Region),新生代和老年代不再物理隔離。

    通過引入 Region 的概念,從而將原來的一整塊內存空間劃分成多個的小空間,使得每個小空間可以單獨進行垃圾回收。這種劃分方法帶來了很大的靈活性,使得可預測的停頓時間模型成為可能。通過記錄每個 Region 垃圾回收時間以及回收所獲得的空間(這兩個值是通過過去回收的經驗獲得),并維護一個優先列表,每次根據允許的收集時間,優先回收價值最大的 Region。

    每個 Region 都有一個 Remembered Set,用來記錄該 Region 對象的引用對象所在的 Region。通過使用 Remembered Set,在做可達性分析的時候就可以避免全堆掃描。

    如果不計算維護 Remembered Set 的操作,G1 收集器的運作大致可劃分為以下幾個步驟:

    • 初始標記:僅僅是標記一下GC Roots能直接關聯到的對象,并且修改TAMS指針的值,讓下一階段用戶線程并發運行時,能正確地在可用的Region中分配新對象。這個階段需要停頓,但耗時很短,并且是借用進行Minor GC的時候同步完成的,所以G1在這階段實際上沒有額外的停頓。每一個Region設計了兩個名為TAMS(Top at Mark Start)的指針,把Region中的一部分空間劃分出來用于并發回收過程中的新對象分配,并發回收時新分配的對象地址都必須在這兩個指針位置上。
    • 并發標記:從GC Root開始對堆中對象進行可達性分析,遞歸掃描整個堆里的對象圖,找出要回收的對象,這階段耗時較長,但可與用戶程序并發執行。當對象圖掃描完成以后,還要重新處理原始快照(SATB)記錄下的在并發時有引用變動的對象。這是整個G1過程中,唯一不需要用戶線程停頓的算法。
    • 最終標記:為了修正在并發標記期間因用戶程序繼續運作而導致標記產生變動的那一部分標記記錄,虛擬機將這段時間對象變化記錄在線程的 Remembered Set Logs 里面,最終標記階段需要把 Remembered Set Logs 的數據合并到 Remembered Set 中。這階段需要停頓線程,但是可并行執行。
    • 篩選回收:首先對各個 Region 中的回收價值和成本進行排序,根據用戶所期望的 GC 停頓時間來制定回收計劃。此階段其實也可以做到與用戶程序一起并發執行,但是因為只回收一部分 Region,時間是用戶可控制的,而且停頓用戶線程將大幅度提高收集效率。

    G1被視為 JDK1.7 中 HotSpot 虛擬機的一個重要進化特征。它具備一下特點:

    • 空間整合:與 CMS 的“標記–清理”算法不同,G1 從整體來看是基于“標記整理”算法實現的收集器;從局部上來看是基于“復制”算法實現的;運行期間不會產生內存空間碎片。
    • 可預測的停頓:這是 G1 相對于 CMS 的另一個大優勢,降低停頓時間是 G1 和 CMS 共同的關注點,但 G1 除了追求低停頓外,還能建立可預測的停頓時間模型,能讓使用者明確指定在一個長度為 M 毫秒的時間片段內。
    • 區域化內存劃片,整體編為一系列不連續的內存區域,避免了全內存區的GC操作。核心思想是將整個堆內存區域分成大小相同的子區域,在JVM啟動時自動設置這些子區域的大小。
    • 在堆的使用上,G1并不要求對象的存儲一定是物理上連續的,只要邏輯上連續即可,每個分區也不會固定地為某個代服務,可以按需在新生代和老年代切換。啟動時可以通過參數-XX:G1HeapRegionSize=n指定分區大小(1MB32MB,且必須是2的冪),默認將整堆劃分為2048個分區。大小范圍在1MB32MB,最多能設置2048個區域,也即最大能夠支持的最大內存為:32MB * 2048 = 65536MB = 64內存。
    • 在G1中,還有一種特效的區域,叫Humongous區域。如果一個對象占用的空間超過了分區容量50%以上,G1收集器就認為這是一個巨型對象。這些巨型對象默認直接會被分配在老年代,但是如果它是一個短期存在的巨型對象,就會對垃圾收集器造成負面影響。為了解決這個問題,G1劃分了一個H區,它用來專門存放巨型對象。如果一個H區裝不下一個巨型對象,那么G1會尋找連續的H分區來存儲。為了能找到連續的H區,有時候不得不啟動Full GC。

    缺點:

    • G1為了垃圾收集產生的內存占用和程序運行時的額外執行負載比CMS要高。

    特點:

    并行與并發
    分代收集,收集范圍包括新生代和老年代
    結合多種垃圾收集算法,空間整合,不產生碎片
    可預測的停頓:低停頓的同時實現高吞吐量
    面向服務端應用,將來替換CMS
    優勢:
    能充分利用多CPU、多核環境下的硬件優勢;
    能獨立管理整個GC堆(新生代和老年代),而不需要與其他收集器搭配;
    不會產生內存碎片,有利于長時間運行;
    除了追求低停頓處,還能建立可預測的停頓時間模型;
    G1收集器是當今收集器技術發展的最前沿成果。

    劣勢:
    G1 需要記憶集 (具體來說是卡表)來記錄新生代和老年代之間的引用關系,這種數據結構在 G1 中需要占用大量的內存,可能達到整個堆內存容量的 20% 甚至更多。而且 G1 中維護記憶集的成本較高,帶來了更高的執行負載,影響效率。

    按照《深入理解Java虛擬機》作者的說法,CMS 在小內存應用上的表現要優于 G1,而大內存應用上 G1 更有優勢,大小內存的界限是6GB到8GB。

    所以,盡管是最前沿的成果,也不是完美無缺的。
    使用場景
    個人以為G1已經基本全面壓制cms、parallel等回收器,缺點見上面的劣勢。但如果不是追求極致的性能,基本可以無腦G1

    參數設置
    -XX:+UseG1GC:指定使用G1收集器;
    -XX:InitiatingHeapOccupancyPercent:當整個Java堆的占用率達到參數值時,開始并發標記階段;默認為45;
    -XX:MaxGCPauseMillis:為G1設置暫停時間目標,默認值為200毫秒;
    -XX:G1HeapRegionSize:設置每個Region大小,范圍1MB到32MB;目標是在最小Java堆時可以擁有約2048個Region;

    ZGC

    • ZGC

    查看當前使用的垃圾收集器

    java -XX:+PrintCommandLineFlags -version

    一些參數

    DefNew -----> Default New Generation Tenured -----> Old ParNew -----> Parallel New Generation PsYoungGen -----> Parallel Scavenge ParOldGen -----> Parallel Old Generation

    配置垃圾收集器

    使用串行垃圾收集器,老年代會自動使用Serial Old收集器:

    java +XX:+UseSerialGC

    啟用ParNew收集器,老年代會使用Serial Old收集器:

    java -XX:+UseParNewGC

    啟用Parallel Scavenge收集器,老年代自動使用Parallel Old收集器:

    java -XX:+UseParallelGC # 或者下面這句 java -XX:+UseParallelOldGCjava -XX:ParallelGCThreads=8 # 表示啟動8個GC線程

    啟用Concurrent Mark Sweep(CMS)收集器,新生代自動使用ParNew:

    java -XX:+UseConcMarkSweepGC

    開啟該參數后,新生代使用ParNew,老年代使用CMS,如果CMS出錯,將使用Serial Old代理CMS收集垃圾。

    啟用G1收集器:

    java -XX:+UseG1GC

    如何選擇垃圾收集器

    • 單CPU或者小內存,單機程序

      -XX:+UseSerialGC
    • 多CPU,需要大量吞吐量,如后臺計算型

      -XX:+UseParallelGC # 或者 -XX:+UseParallelOldGC
    • 多CPU,追求低停頓時間,需要快速響應,如互聯網應用

      -XX:UseConcMarkSweepGC # 或者 -XX:+ParNewGC

    低延遲垃圾收集器

    衡量垃圾收集器的三項重要指標:

    • 內存占用
    • 吞吐量
    • 延遲

    隨著計算機硬件的發展、性能的提升,延遲的重要性日益凸顯。

    Shenandoah和ZGC垃圾收集器,幾乎整個工作過程全部都是并發的,只有初始標記、最終標記這些階段有短暫的停頓,這部分停頓時間基本上是固定的,與堆的容量、堆中對象的數量沒有正比例關系,停頓時間不超過10毫秒。

    Shenandoah收集器

    以后更新

    ZGC收集器

    以后更新

    選擇合適的垃圾收集器

    Epsilon收集器

    Epsilon收集器是一個不能進行垃圾收集的垃圾收集器。一個垃圾收集器除了垃圾收集這個本職工作之外,它還要負責堆的管理與布局、對象的分配、與解釋器的協作、與編譯器的協作、與監控子系統協作等職責。Epsilon收集器主要負責這部分工作。

    JVM垃圾收集器總結

    本文主要介紹了JVM中的垃圾回收器,主要包括串行回收器、并行回收器以及CMS回收器、G1回收器。他們各自都有優缺點,通常來說你需要根據你的業務,進行基于垃圾回收器的性能測試,然后再做選擇。下面給出配置回收器時,經常使用的參數:

    -XX:+UseSerialGC:在新生代和老年代使用串行收集器
    -XX:+UseParNewGC:在新生代使用并行收集器
    -XX:+UseParallelGC :新生代使用并行回收收集器,更加關注吞吐量
    -XX:+UseParallelOldGC:老年代使用并行回收收集器
    -XX:ParallelGCThreads:設置用于垃圾回收的線程數
    -XX:+UseConcMarkSweepGC:新生代使用并行收集器,老年代使用CMS+串行收集器
    -XX:ParallelCMSThreads:設定CMS的線程數量
    -XX:+UseG1GC:啟用G1垃圾回收器

    JVM調優

    JVM參數類型

    標配參數

    java -versionjava -helpjava -showversion

    X參數

    解釋執行

    java -Xint

    第一次使用就編譯成本地代碼

    java -Xcomp

    混合模式

    java -Xmixed

    XX參數

    Boolean類型

    -XX:+ 或者 -某個屬性值 + 表示開啟 - 表示關閉

    查看正在運行的java程序:

    jps -l

    查看某個java程序的某個jvm參數是否開啟:

    jinfo -flag jvm參數 進程號

    例如:

    jinfo -flag PrintGCDetails 進程號 # 查看這個java程序是否開始GC日志

    查看某個java程序的所有jvm參數:

    jinfo -flags 進程號

    是否使用串行垃圾回收器:

    -XX:-UseSerialGC +XX:+UseSerialGC

    KV設值類型

    -XX:屬性key=屬性值value

    使用例子:

    -XX:MetaspaceSize=128m # 設置元空間的大小 -XX:MaxTenuringThreshold=15 # 年輕代升老年代的閾值

    -Xms等價于-XX:InitialHeapSize;-Xmx等價于-XX:MaxHeapSize

    jinfo舉例,如何查看當前運行程序的配置

    查看jvm初始化參數:

    java -XX:+PrintFlagsInitial

    查看jvm修改更新后的參數:

    java -XX:PrintFlagsFinal

    ":= "代表UseParallelGC被修改過,沒有被修改就是“=”

    查看參數:

    java -XX:+PrintCommandLineFlags -version

    JVM常用配置參數

    -Xms 和 -Xmx

    -Xms和-Xmx設置為一樣大小,默認為物理內存的四分之一

    -Xss

    設置單個線程棧的大小,一般默認為512k~1024k

    -Xss等價于-XX:ThreadStackSize

    -Xmn

    設置新生代的大小

    -XX:MetaspaceSize

    設置元空間大小

    -XX:+PrintGCDetails

    輸出GC的詳細信息

    Minor GC

    Full GC

    設置參數案例

    -Xms128m -Xms4096m -Xss1024k -XX:MetaspaceSize=512m -XX:+PrintCommandLineFlags -XX:+PrintGCDetails -XX:+UseSerialGC

    -XX:SurvivorRatio

    新生代默認比例:

    Eden :from survivor : to survivo = 8 : 1 : 1

    jvm默認新生代參數:

    -XX:SurvivorRatio=8 # 這就是上面的8:1:1

    -XX:NewRatio

    配置新生代和老年代在堆結構中的占比。

    默認-XX:NewRatio=2,即新生代 : 老年代=1 : 2

    -XX:MaxTenuringThreshold

    設置新生代升老年代的閾值,默認是15,最大也是15,因為只用4bit存儲這個值。

    如何查看JVM系統默認值

    類文件結構

    概述

    在 Java 中,JVM 可以理解的代碼就叫做字節碼(即擴展名為 .class 的文件),它不面向任何特定的處理器,只面向虛擬機。Java 語言通過字節碼的方式,在一定程度上解決了傳統解釋型語言執行效率低的問題,同時又保留了解釋型語言可移植的特點。所以 Java 程序運行時比較高效,而且,由于字節碼并不針對一種特定的機器,因此,Java 程序無須重新編譯便可在多種不同操作系統的計算機上運行。

    Clojure(Lisp 語言的一種方言)、Groovy、Scala 等語言都是運行在 Java 虛擬機之上。下圖展示了不同的語言被不同的編譯器編譯成.class文件最終運行在 Java 虛擬機之上。.class文件的二進制格式可以使用 WinHex 查看。

    可以說.class文件是不同的語言在 Java 虛擬機之間的重要橋梁,同時也是支持 Java 跨平臺很重要的一個原因。

    Class 文件結構總結

    根據 Java 虛擬機規范,類文件由單個 ClassFile 結構組成:

    ClassFile {u4 magic; //Class 文件的標志u2 minor_version;//Class 的小版本號u2 major_version;//Class 的大版本號u2 constant_pool_count;//常量池的數量cp_info constant_pool[constant_pool_count-1];//常量池u2 access_flags;//Class 的訪問標記u2 this_class;//當前類u2 super_class;//父類u2 interfaces_count;//接口u2 interfaces[interfaces_count];//一個類可以實現多個接口u2 fields_count;//Class 文件的字段屬性field_info fields[fields_count];//一個類會可以有個字段u2 methods_count;//Class 文件的方法數量method_info methods[methods_count];//一個類可以有個多個方法u2 attributes_count;//此類的屬性表中的屬性數attribute_info attributes[attributes_count];//屬性表集合 }

    下面詳細介紹一下 Class 文件結構涉及到的一些組件。

    Class文件字節碼結構組織示意圖 (之前在網上保存的,非常不錯,原出處不明):

    2.1 魔數

    u4 magic; //Class 文件的標志

    每個 Class 文件的頭四個字節稱為魔數(Magic Number),它的唯一作用是確定這個文件是否為一個能被虛擬機接收的 Class 文件。

    程序設計者很多時候都喜歡用一些特殊的數字表示固定的文件類型或者其它特殊的含義。

    2.2 Class 文件版本

    u2 minor_version;//Class 的小版本號u2 major_version;//Class 的大版本號

    緊接著魔數的四個字節存儲的是 Class 文件的版本號:第五和第六是次版本號,第七和第八是主版本號。

    高版本的 Java 虛擬機可以執行低版本編譯器生成的 Class 文件,但是低版本的 Java 虛擬機不能執行高版本編譯器生成的 Class 文件。所以,我們在實際開發的時候要確保開發的的 JDK 版本和生產環境的 JDK 版本保持一致。

    2.3 常量池

    u2 constant_pool_count;//常量池的數量cp_info constant_pool[constant_pool_count-1];//常量池

    緊接著主次版本號之后的是常量池,常量池的數量是 constant_pool_count-1(常量池計數器是從1開始計數的,將第0項常量空出來是有特殊考慮的,索引值為0代表“不引用任何一個常量池項”)。

    常量池主要存放兩大常量:字面量和符號引用。字面量比較接近于 Java 語言層面的的常量概念,如文本字符串、聲明為 final 的常量值等。而符號引用則屬于編譯原理方面的概念。包括下面三類常量:

    • 類和接口的全限定名
    • 字段的名稱和描述符
    • 方法的名稱和描述符

    常量池中每一項常量都是一個表,這14種表有一個共同的特點:開始的第一位是一個 u1 類型的標志位 -tag 來標識常量的類型,代表當前這個常量屬于哪種常量類型.

    類型標志(tag)描述
    CONSTANT_utf8_info1UTF-8編碼的字符串
    CONSTANT_Integer_info3整形字面量
    CONSTANT_Float_info4浮點型字面量
    CONSTANT_Long_info長整型字面量
    CONSTANT_Double_info雙精度浮點型字面量
    CONSTANT_Class_info類或接口的符號引用
    CONSTANT_String_info字符串類型字面量
    CONSTANT_Fieldref_info字段的符號引用
    CONSTANT_Methodref_info10類中方法的符號引用
    CONSTANT_InterfaceMethodref_info11接口中方法的符號引用
    CONSTANT_NameAndType_info12字段或方法的符號引用
    CONSTANT_MothodType_info16標志方法類型
    CONSTANT_MethodHandle_info15表示方法句柄
    CONSTANT_InvokeDynamic_info18表示一個動態方法調用點

    .class 文件可以通過javap -v class類名 指令來看一下其常量池中的信息(javap -v class類名-> temp.txt :將結果輸出到 temp.txt 文件)。

    2.4 訪問標志

    在常量池結束之后,緊接著的兩個字節代表訪問標志,這個標志用于識別一些類或者接口層次的訪問信息,包括:這個 Class 是類還是接口,是否為 public 或者 abstract 類型,如果是類的話是否聲明為 final 等等。

    類訪問和屬性修飾符:

    我們定義了一個 Employee 類

    package top.snailclimb.bean; public class Employee {... }

    通過javap -v class類名 指令來看一下類的訪問標志。

    2.5 當前類索引,父類索引與接口索引集合

    u2 this_class;//當前類u2 super_class;//父類u2 interfaces_count;//接口u2 interfaces[interfaces_count];//一個類可以實現多個接口

    類索引用于確定這個類的全限定名,父類索引用于確定這個類的父類的全限定名,由于 Java 語言的單繼承,所以父類索引只有一個,除了 java.lang.Object 之外,所有的 java 類都有父類,因此除了 java.lang.Object 外,所有 Java 類的父類索引都不為 0。

    接口索引集合用來描述這個類實現了那些接口,這些被實現的接口將按implents(如果這個類本身是接口的話則是extends) 后的接口順序從左到右排列在接口索引集合中。

    2.6 字段表集合

    u2 fields_count;//Class 文件的字段的個數field_info fields[fields_count];//一個類會可以有個字段

    字段表(field info)用于描述接口或類中聲明的變量。字段包括類級變量以及實例變量,但不包括在方法內部聲明的局部變量。

    field info(字段表) 的結構:

    • access_flags: 字段的作用域(public ,private,protected修飾符),是實例變量還是類變量(static修飾符),可否被序列化(transient 修飾符),可變性(final),可見性(volatile 修飾符,是否強制從主內存讀寫)。
    • name_index: 對常量池的引用,表示的字段的名稱;
    • descriptor_index: 對常量池的引用,表示字段和方法的描述符;
    • attributes_count: 一個字段還會擁有一些額外的屬性,attributes_count 存放屬性的個數;
    • attributes[attributes_count]: 存放具體屬性具體內容。

    上述這些信息中,各個修飾符都是布爾值,要么有某個修飾符,要么沒有,很適合使用標志位來表示。而字段叫什么名字、字段被定義為什么數據類型這些都是無法固定的,只能引用常量池中常量來描述。

    字段的 access_flags 的取值:

    2.7 方法表集合

    u2 methods_count;//Class 文件的方法的數量method_info methods[methods_count];//一個類可以有個多個方法

    methods_count 表示方法的數量,而 method_info 表示的方法表。

    Class 文件存儲格式中對方法的描述與對字段的描述幾乎采用了完全一致的方式。方法表的結構如同字段表一樣,依次包括了訪問標志、名稱索引、描述符索引、屬性表集合幾項。

    method_info(方法表的) 結構:

    方法表的 access_flag 取值:

    注意:因為volatile修飾符和transient修飾符不可以修飾方法,所以方法表的訪問標志中沒有這兩個對應的標志,但是增加了synchronized、native、abstract等關鍵字修飾方法,所以也就多了這些關鍵字對應的標志。

    2.8 屬性表集合

    u2 attributes_count;//此類的屬性表中的屬性數attribute_info attributes[attributes_count];//屬性表集合

    在 Class 文件,字段表,方法表中都可以攜帶自己的屬性表集合,以用于描述某些場景專有的信息。與 Class 文件中其它的數據項目要求的順序、長度和內容不同,屬性表集合的限制稍微寬松一些,不再要求各個屬性表具有嚴格的順序,并且只要不與已有的屬性名重復,任何人實現的編譯器都可以向屬性表中寫 入自己定義的屬性信息,Java 虛擬機運行時會忽略掉它不認識的屬性。

    參考鏈接

    • JavaGuide

    虛擬機類加載機制

    類的生命周期

    一個類的完整生命周期如下:

    [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-PR2UnqcU-1624851354188)(http://wardseptember.top/20200818171655.png)]

    類加載過程

    Class 文件需要加載到虛擬機中之后才能運行和使用,那么虛擬機是如何加載這些 Class 文件呢?

    系統加載 Class 類型的文件主要三步:加載->連接->初始化。連接過程又可分為三步:驗證->準備->解析。

    加載

    class文件的加載時機:

    • 1 遇到 new、getstatic、putstatic、或invokestatic這四條字節碼指令 2 使用
      java.lang.reflect 包的方法對類進行反射調用的時候 3 初始化類時,父類沒有被初始化,先初始化父類
      4 虛擬機啟動時,用戶指定的主類(包含main()的那個類)
      5 當使用JDK1.7動態語言支持的時,如果一個java.lang.invoke.MethodHandle
      實例最后解析的結果REF_getStatic、REF_putStatic、REF_invokeStatic的方法句柄,并且這個方法句柄鎖對應的類沒有進行過初始化時

    關于序號1的詳細解釋:

    使用 new 關鍵字實例化對象時
    讀取類的靜態變量時(被 final修飾,已在編譯期把結果放入常量池的靜態字段除外)
    設置類的靜態變量時
    調用一個類的靜態方法時
    注意: newarray指令觸發的只是數組類型本身的初始化,而不會導致其相關類型的初始化,比如,new String[]只會直接觸發 String[]類的初始化,也就是觸發對類[Ljava.lang.String的初始化,而直接不會觸發String類的初始化。

    生成這四條指令最常見的Java代碼場景是:

    對于這5種會觸發類進行初始化的場景,虛擬機規范中使用了一個很強烈的限定語:“有且只有”,這5種場景中的行為稱為對一個類進行主動引用。除此之外,所有引用類的方式都不會觸發初始化,稱為 被動引用。

    需要特別指出的是,類的實例化和類的初始化是兩個完全不同的概念:

    類的實例化是指創建一個類的實例(對象)的過程;
    類的初始化是指為類各個成員賦初始值的過程,是類生命周期中的一個階段;
    被動引用的三個場景:

    通過子類引用父類的靜態字段,不會導致子類初始化

    public class Test1 {

    static {System.out.println("Init Superclass!!!"); }public static void main(String[] args) {int x = Son.count; }

    }

    class Father extends Test1{
    static int count = 1;
    static {
    System.out.println(“Init father!!!”);
    }
    }

    class Son extends Father{
    static {
    System.out.println(“Init son!!!”);
    }
    }

    輸出:

    Init Superclass!!!
    Init father!!!
    1
    2
    對于靜態字段,只有直接定義這個字段的類才會被初始化,因此通過其子類來引用父類中定義的靜態字段,只會觸發父類的初始化而不會觸發子類的初始化。至于是否要觸發子類的加載和驗證,在虛擬機中并未明確規定,這點取決于虛擬機的具體實現。對于Sun HotSpot虛擬機來說,可通過-XX:+TraceClassLoading參數觀察到此操作會導致子類的加載。

    上面的案例中,由于count字段是在Father類中定義的,因此該類會被初始化,此外,在初始化類Father的時候,虛擬機發現其父類Test1 還沒被初始化,因此虛擬機將先初始化其父類Test1 ,然后初始化子類Father,而Son始終不會被初始化;

    通過數組定義來引用類,不會觸發此類的初始化

    public class Test2 {

    public static void main(String[] args) {M[] m = new M[8]; }

    }

    class M{
    static {
    System.out.println(“Init M!!!”);
    }
    }

    運行之后我們會發現沒有輸出 “Init M!!!”,說明沒有觸發類的初始化階段

    常量在編譯階段會存入調用類的常量池中,本質上并沒有直接引用到定義常量的類,因此不會觸發定義常量的類的初始化

    public class Test3 {

    public static void main(String[] args) {System.out.println(ConstClass.COUNT); }

    }

    class ConstClass{
    static final int COUNT = 1;
    static{
    System.out.println(“Init ConstClass!!!”);
    }
    }

    上面代碼運行后也沒有輸出 Init ConstClass!!!,這是因為雖然在Java源碼中引用了ConstClass 類中的常量COUNT ,但其實在編譯階段通過常量傳播優化,已經將常量的值 "1"存儲到Test3 常量池中了,對常量ConstClass.COUNT的引用實際都被轉化為Test3 類對自身常量池的引用了,也就是說,實際上Test3 的Class文件之中并沒有ConstClass類的符號引用入口,這兩個類在編譯為Class文件之后就不存在關系

    類加載過程的第一步,主要完成下面3件事情:

  • 通過全類名獲取定義此類的二進制字節流
  • 將字節流所代表的靜態存儲結構轉換為方法區的運行時數據結構
  • 在內存中生成一個代表該類的 Class 對象,作為方法區這些數據的訪問入口
  • 虛擬機規范多上面這3點并不具體,因此是非常靈活的。比如:“通過全類名獲取定義此類的二進制字節流” 并沒有指明具體從哪里獲取、怎樣獲取。比如:比較常見的就是從 ZIP 包中讀取(日后出現的JAR、EAR、WAR格式的基礎)、其他文件生成(典型應用就是JSP)等等。

    一個非數組類的加載階段(加載階段獲取類的二進制字節流的動作)是可控性最強的階段,這一步我們可以去完成還可以自定義類加載器去控制字節流的獲取方式(重寫一個類加載器的 loadClass() 方法)。數組類型不通過類加載器創建,它由 Java 虛擬機直接創建。

    類加載器、雙親委派模型也是非常重要的知識點,這部分內容會在后面的文章中單獨介紹到。

    加載階段和連接階段的部分內容是交叉進行的,加載階段尚未結束,連接階段可能就已經開始了。

    驗證

    準備

    準備階段是正式為類變量分配內存并設置類變量初始值的階段,這些內存都將在方法區中分配。對于該階段有以下幾點需要注意:

  • 這時候進行內存分配的僅包括類變量(static),而不包括實例變量,實例變量會在對象實例化時隨著對象一塊分配在 Java 堆中。
  • 這里所設置的初始值"通常情況"下是數據類型默認的零值(如0、0L、null、false等),比如我們定義了public static int value=111 ,那么 value 變量在準備階段的初始值就是 0 而不是111(初始化階段才會賦值)。特殊情況:比如給 value 變量加上了 fianl 關鍵字public static final int value=111 ,那么準備階段 value 的值就被賦值為 111。
  • 基本數據類型的零值:

    解析

    解析階段是虛擬機將常量池內的符號引用替換為直接引用的過程。解析動作主要針對類或接口、字段、類方法、接口方法、方法類型、方法句柄和調用限定符7類符號引用進行。

    符號引用就是一組符號來描述目標,可以是任何字面量。直接引用就是直接指向目標的指針、相對偏移量或一個間接定位到目標的句柄。在程序實際運行時,只有符號引用是不夠的,舉個例子:在程序執行方法時,系統需要明確知道這個方法所在的位置。Java 虛擬機為每個類都準備了一張方法表來存放類中所有的方法。當需要調用一個類的方法的時候,只要知道這個方法在方發表中的偏移量就可以直接調用該方法了。通過解析操作符號引用就可以直接轉變為目標方法在類中方法表的位置,從而使得方法可以被調用。

    綜上,解析階段是虛擬機將常量池內的符號引用替換為直接引用的過程,也就是得到類或者字段、方法在內存中的指針或者偏移量。

    初始化

    初始化是類加載的最后一步,也是真正執行類中定義的 Java 程序代碼(字節碼),初始化階段是執行類構造器 <clinit> ()方法的過程。

    對于<clinit>() 方法的調用,虛擬機會自己確保其在多線程環境中的安全性。因為 <clinit>() 方法是帶鎖線程安全,所以在多線程環境下進行類初始化的話可能會引起死鎖,并且這種死鎖很難被發現。

    主動引用

    對于初始化階段,虛擬機嚴格規范了有且只有5種情況下,必須對類進行初始化(只有主動去使用類才會初始化類):

  • 當遇到 new 、 getstatic、putstatic或invokestatic 這4條直接碼指令時,比如 new 一個類,讀取一個靜態字段(未被 final 修飾)、或調用一個類的靜態方法時。
    • 當jvm執行new指令時會初始化類。即當程序創建一個類的實例對象。
    • 當jvm執行getstatic指令時會初始化類。即程序訪問類的靜態變量(不是靜態常量,常量會被加載到運行時常量池)。
    • 當jvm執行putstatic指令時會初始化類。即程序給類的靜態變量賦值。
    • 當jvm執行invokestatic指令時會初始化類。即程序調用類的靜態方法。
  • 使用 java.lang.reflect 包的方法對類進行反射調用時如Class.forname("…"),newInstance()等等。 ,如果類沒初始化,需要觸發其初始化。
  • 初始化一個類,如果其父類還未初始化,則先觸發該父類的初始化。
  • 當虛擬機啟動時,用戶需要定義一個要執行的主類 (包含 main 方法的那個類),虛擬機會先初始化這個類。
  • MethodHandle和VarHandle可以看作是輕量級的反射調用機制,而要想使用這2個調用, 就必須先使用findStaticVarHandle來初始化要調用的類。
  • 當一個接口中定義了JDK8新加入的默認方法(被default關鍵字修飾的接口方法)時,如果有這個接口的實現類發生了初始化,那該接口要在其之前被初始化。
  • 被動引用

    以上6 種場景中的行為稱為對一個類進行主動引用。除此之外,所有引用類的方式都不會觸發初始化,稱為被動引用。被動引用的常見例子包括:

    • 通過子類引用父類的靜態字段,不會導致子類初始化。
    System.out.println(SubClass.value); // value 字段在 SuperClass 中定義Copy to clipboardErrorCopied
    • 通過數組定義來引用類,不會觸發此類的初始化。該過程會對數組類進行初始化,數組類是一個由虛擬機自動生成的、直接繼承自 Object 的子類,其中包含了數組的屬性和方法。
    SuperClass[] sca = new SuperClass[10];Copy to clipboardErrorCopied
    • 常量在編譯階段會存入調用類的常量池中,本質上并沒有直接引用到定義常量的類,因此不會觸發定義常量的類的初始化。
    System.out.println(ConstClass.HELLOWORLD);

    卸載

    卸載類即該類的Class對象被GC。

    卸載類需要滿足3個要求:

  • 該類的所有的實例對象都已被GC,也就是說堆不存在該類的實例對象。
  • 該類沒有在其他任何地方被引用
  • 該類的類加載器的實例已被GC
  • 所以,在JVM生命周期類,由jvm自帶的類加載器加載的類是不會被卸載的。但是由我們自定義的類加載器加載的類是可能被卸載的。

    只要想通一點就好了,jdk自帶的BootstrapClassLoader,PlatformClassLoader,AppClassLoader負責加載jdk提供的類,所以它們(類加載器的實例)肯定不會被回收。而我們自定義的類加載器的實例是可以被回收的,所以使用我們自定義加載器加載的類是可以被卸載掉的。

    參考鏈接

    • JavaGuide

    類加載器

    所有的類都由類加載器加載,加載的作用就是將 .class文件加載到內存。

    JVM 中內置了三個重要的 ClassLoader,除了 BootstrapClassLoader 其他類加載器均由 Java 實現且全部繼承自java.lang.ClassLoader:

  • BootstrapClassLoader(啟動類加載器) :最頂層的加載類,由C++實現,負責加載 %JAVA_HOME%/lib目錄下的jar包和類或者或被 -Xbootclasspath參數指定的路徑中的所有類。
  • ExtensionClassLoader(擴展類加載器) :主要負責加載目錄 %JRE_HOME%/lib/ext 目錄下的jar包和類,或被 java.ext.dirs 系統變量所指定的路徑下的jar包。
  • AppClassLoader(應用程序類加載器) :面向我們用戶的加載器,負責加載當前應用classpath下的所有jar包和類。
  • 雙親委派模型

    每一個類都有一個對應它的類加載器。系統中的 ClassLoder 在協同工作的時候會默認使用 雙親委派模型 。即在類加載的時候,系統會首先判斷當前類是否被加載過。已經被加載的類會直接返回,否則才會嘗試加載。加載的時候,首先會把該請求委派該父類加載器的 loadClass() 處理,因此所有的請求最終都應該傳送到頂層的啟動類加載器 BootstrapClassLoader 中。當父類加載器無法處理時,才由自己來處理。當父類加載器為null時,會使用啟動類加載器 BootstrapClassLoader 作為父類加載器。

    每個類加載都有一個父類加載器,我們通過下面的程序來驗證。

    public class ClassLoaderDemo {public static void main(String[] args) {System.out.println("ClassLodarDemo's ClassLoader is " + ClassLoaderDemo.class.getClassLoader());System.out.println("The Parent of ClassLodarDemo's ClassLoader is " + ClassLoaderDemo.class.getClassLoader().getParent());System.out.println("The GrandParent of ClassLodarDemo's ClassLoader is " + ClassLoaderDemo.class.getClassLoader().getParent().getParent());} }

    Output

    ClassLodarDemo's ClassLoader is sun.misc.Launcher$AppClassLoader@18b4aac2 The Parent of ClassLodarDemo's ClassLoader is sun.misc.Launcher$ExtClassLoader@1b6d3586 The GrandParent of ClassLodarDemo's ClassLoader is null

    AppClassLoader的父類加載器為ExtClassLoader ExtClassLoader的父類加載器為null,null并不代表ExtClassLoader沒有父類加載器,而是 BootstrapClassLoader 。

    其實這個雙親翻譯的容易讓別人誤解,我們一般理解的雙親都是父母,這里的雙親更多地表達的是“父母這一輩”的人而已,并不是說真的有一個 Mother ClassLoader 和一個 Father ClassLoader 。另外,類加載器之間的“父子”關系也不是通過繼承來體現的,是由“優先級”來決定。官方API文檔對這部分的描述如下:

    The Java platform uses a delegation model for loading classes. The basic idea is that every class loader has a “parent” class loader. When loading a class, a class loader first “delegates” the search for the class to its parent class loader before attempting to find the class itself.

    雙親委派模型實現源碼分析

    雙親委派模型的實現代碼非常簡單,邏輯非常清晰,都集中在 java.lang.ClassLoader 的 loadClass() 中,相關代碼如下所示。

    private final ClassLoader parent; protected Class<?> loadClass(String name, boolean resolve)throws ClassNotFoundException{synchronized (getClassLoadingLock(name)) {// 首先,檢查請求的類是否已經被加載過Class<?> c = findLoadedClass(name);if (c == null) {long t0 = System.nanoTime();try {if (parent != null) {//父加載器不為空,調用父加載器loadClass()方法處理c = parent.loadClass(name, false);} else {//父加載器為空,使用啟動類加載器 BootstrapClassLoader 加載c = findBootstrapClassOrNull(name);}} catch (ClassNotFoundException e) {//拋出異常說明父類加載器無法完成加載請求}if (c == null) {long t1 = System.nanoTime();//自己嘗試加載c = findClass(name);// this is the defining class loader; record the statssun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);sun.misc.PerfCounter.getFindClasses().increment();}}if (resolve) {resolveClass(c);}return c;}}

    雙親委派模型的好處

    雙親委派模型保證了Java程序的穩定運行,可以避免類的重復加載(JVM 區分不同類的方式不僅僅根據類名,相同的類文件被不同的類加載器加載產生的是兩個不同的類),也保證了 Java 的核心 API 不被篡改。如果沒有使用雙親委派模型,而是每個類加載器加載自己的話就會出現一些問題,比如我們編寫一個稱為 java.lang.Object 類的話,那么程序運行的時候,系統就會出現多個不同的 Object 類。

    • 避免類的重復加載
    • 打破雙親委派模型,實現類之間的隔離,還可以實現熱部署

    如果我們不想用雙親委派模型怎么辦?

    自定義加載器的話,需要繼承 ClassLoader 。如果我們不想打破雙親委派模型,就重寫 ClassLoader 類中的 findClass() 方法即可,無法被父類加載器加載的類最終會通過這個方法被加載。但是,如果想打破雙親委派模型則需要重寫 loadClass() 方法

    自定義類加載器

    除了 BootstrapClassLoader 其他類加載器均由 Java 實現且全部繼承自java.lang.ClassLoader。如果我們要自定義自己的類加載器,很明顯需要繼承 ClassLoader。

    tomcat 為什么打破雙親委派模型

    我們思考一下:Tomcat是個web容器, 那么它要解決什么問題:

  • 一個web容器可能需要部署兩個應用程序,不同的應用程序可能會依賴同一個第三方類庫的不同版本,不能要求同一個類庫在同一個服務器只有一份,因此要保證每個應用程序的類庫都是獨立的,保證相互隔離。
  • 部署在同一個web容器中相同的類庫相同的版本可以共享。否則,如果服務器有10個應用程序,那么要有10份相同的類庫加載進虛擬機,這是扯淡的。
  • web容器也有自己依賴的類庫,不能于應用程序的類庫混淆。基于安全考慮,應該讓容器的類庫和程序的類庫隔離開來。
  • web容器要支持jsp的修改,我們知道,jsp 文件最終也是要編譯成class文件才能在虛擬機中運行,但程序運行后修改jsp已經是司空見慣的事情,否則要你何用? 所以,web容器需要支持 jsp 修改后不用重啟。
  • 參考鏈接

    • JavaGuide

    JVM調優

    概述

    為什么調優

    • 防止出現OOM
    • 解決OOM
    • 減少Full GC出現的頻率

    性能優化的步驟

  • 性能監控

    • GC 頻繁
    • cpu load 過高
    • OOM
    • 內存泄露
    • 死鎖
    • 程序響應時間較長
  • 性能優化

    • 打印GC日志,通過GCviewer或者http://gceasy.io 來分析日志信息
    • 靈活運用命令行工具,jstack、jmap、jinfo等
    • dump出堆文件,使用內存分析工具分析文件
    • 使用阿里Arthas,或jconsole、JVisualVM來實時查看JVM狀態
    • jstack查看堆棧信息
  • 性能調優

    • 適當增加內存,根據業務背景選擇垃圾收集器
    • 優化代碼,控制內存使用
    • 增加機器,分散節點壓力
    • 合理設置線程池線程數量
    • 使用中間件提高程序效率,比如緩存、消息隊列
  • 性能評價指標

  • 停頓時間

    提交請求和返回該請求的響應之間使用的時間,一般比較關注平均響應時間。

    常用操作的響應時間列表:


    在垃圾回收環節中:

    暫停時間:執行垃圾收集時,程序的工作線程被暫停的時間。

  • 吞吐量

    對單位時間內完成的工作量的量度。

    在GC中,吞吐量指運行用戶代碼的時間占總運行時間的比例,吞吐量為1-1/(1+n)。-XX:GCTimeRatio=n

  • 并發數

    同一時刻,對服務器有實際交互的請求數

  • 內存占用

    Java堆區所占的內存大小

  • 性能監控及診斷工具

    jps

    Jps(Java Process Status)可以顯示指定系統內所有的HotSpot虛擬機內正在運行的進程。

    基本語法

    Jps [options] [hostid]

    options參數如下圖:


    jstat

    jstat(JVM Statistics Monitoring Tool)查看JVM統計信息

    基本語法

    jstat -<option> [-t] [-h<lines] <vmid> [<interval [<count>]]

    Jstat -h 查看命令相關參數



    • -h3表示每輸出三行打印一遍表頭
    • vmid指定進程id
    • interval是查看間隔,單位毫秒
    • count是輸出多少次
    • -t可以再輸出信息前加一個Timestamp列,顯示程序的運行時間,單位是秒

    判斷內存泄露


    jinfo

    Jinfo(Configuration Info for Java) 查看虛擬機配置參數信息,也可用于調整虛擬機的配置參數。

    基本語法

    Jinfo [options] pid



    jmap

    Jmap(JVM Memory Map):一方面是獲取dump文件(堆轉儲快照文件,二進制文件),它還可以獲取目標Java進程的內存相關信息,包括Java堆各區域的使用情況、堆中對象的統計信息、類加載信息等。



    導出內存映像文件




    顯示堆內存相關信息

    • Jmap -heap pid
    • Jmap -histo pid
    • Jmap -permstat pid 查看系統的ClassLoader信息
    • Jmap -finalizerinfo 查看堆積在finalizer隊列中的對象

    jat

    Jhat(JVM Heap Analysis Tool)是JDK自帶的堆分析工具


    基本語法

    jhat [option] [dumpfile]


    Jstack(JVM Stack Trace)

    Jstack:用于生成虛擬機指定進程當前時刻的線程快照(虛擬機堆棧跟蹤)。線程快照就是當前虛擬機內指定進程的每一條線程正在執行的方法堆棧的集合。



    jcmd



    jstatd


    圖形化工具




    Jconsole


    Visual VM




    主要功能


    MAT






    tomcat


    JProfile






    Arthas







    命令


    • 官網教程


    Java Mission Control







    Flame Graphs


    Tprofiler


    內存泄露







    靜態集合類


    單例模式


    內部類持有外部類


    各種連接


    變量不合理的作用域


    改變哈希值


    緩存泄漏


    監聽器和回調


    JVM運行時參數






    java -X



























    分析日志








    Minor GC日志解析




    Full GC日志分析




    GC Easy



    GCViewer


    性能優化


    總結

    以上是生活随笔為你收集整理的JVM系统学习的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    天天爽夜夜爽夜夜爽 | 精品水蜜桃久久久久久久 | 国产特级毛片aaaaaa高潮流水 | 好爽又高潮了毛片免费下载 | 日本一卡2卡3卡四卡精品网站 | 丰满少妇熟乱xxxxx视频 | 色一情一乱一伦 | 天干天干啦夜天干天2017 | 亚洲国产日韩a在线播放 | 精品无码一区二区三区的天堂 | 麻豆成人精品国产免费 | 人人澡人摸人人添 | 在线亚洲高清揄拍自拍一品区 | 亚洲国产av美女网站 | 国产成人精品视频ⅴa片软件竹菊 | 亚洲精品成人av在线 | 久在线观看福利视频 | 精品熟女少妇av免费观看 | 久久亚洲中文字幕无码 | 国产凸凹视频一区二区 | 午夜无码区在线观看 | 中文无码成人免费视频在线观看 | 亚洲国产欧美日韩精品一区二区三区 | 综合激情五月综合激情五月激情1 | 人妻少妇精品无码专区二区 | aa片在线观看视频在线播放 | 人妻无码αv中文字幕久久琪琪布 | 男女超爽视频免费播放 | 国産精品久久久久久久 | 中文字幕人妻无码一区二区三区 | 少妇人妻大乳在线视频 | 日本一卡2卡3卡4卡无卡免费网站 国产一区二区三区影院 | 国产午夜福利亚洲第一 | 牛和人交xxxx欧美 | 亚洲中文无码av永久不收费 | 国产成人无码区免费内射一片色欲 | 精品欧洲av无码一区二区三区 | 国产成人一区二区三区在线观看 | 国产av一区二区三区最新精品 | 精品久久久中文字幕人妻 | 国产乱子伦视频在线播放 | 精品一区二区三区无码免费视频 | 在线天堂新版最新版在线8 | 精品国产成人一区二区三区 | 在线欧美精品一区二区三区 | 亚洲成av人片天堂网无码】 | 亚洲经典千人经典日产 | 强奷人妻日本中文字幕 | 国产精品免费大片 | 亚洲aⅴ无码成人网站国产app | 六月丁香婷婷色狠狠久久 | 亚洲精品中文字幕 | 十八禁真人啪啪免费网站 | 国内丰满熟女出轨videos | 又湿又紧又大又爽a视频国产 | 国产精品久久久久久无码 | 亚洲の无码国产の无码影院 | 国产精品无码成人午夜电影 | 男人的天堂2018无码 | 无码国产色欲xxxxx视频 | 亚洲 另类 在线 欧美 制服 | 欧美肥老太牲交大战 | 亚洲国产精品无码久久久久高潮 | 激情内射亚州一区二区三区爱妻 | 曰韩无码二三区中文字幕 | 欧美 丝袜 自拍 制服 另类 | 精品无人区无码乱码毛片国产 | 高潮毛片无遮挡高清免费视频 | 一个人看的www免费视频在线观看 | 无遮无挡爽爽免费视频 | 久久精品一区二区三区四区 | 性生交大片免费看女人按摩摩 | 国产艳妇av在线观看果冻传媒 | 国产午夜视频在线观看 | 成人综合网亚洲伊人 | 国产精品a成v人在线播放 | 精品国产乱码久久久久乱码 | 又大又黄又粗又爽的免费视频 | 国产精品va在线观看无码 | 国产成人一区二区三区别 | 最新国产乱人伦偷精品免费网站 | 亚洲娇小与黑人巨大交 | 清纯唯美经典一区二区 | 97精品国产97久久久久久免费 | 久久无码中文字幕免费影院蜜桃 | 噜噜噜亚洲色成人网站 | 一本无码人妻在中文字幕免费 | 少妇被粗大的猛进出69影院 | 国产成人精品视频ⅴa片软件竹菊 | 国产偷抇久久精品a片69 | 国产综合久久久久鬼色 | 久久zyz资源站无码中文动漫 | 国产亚洲精品久久久ai换 | 久久亚洲国产成人精品性色 | 欧美熟妇另类久久久久久多毛 | 国产精品美女久久久 | 亚洲高清偷拍一区二区三区 | 欧美阿v高清资源不卡在线播放 | 一本大道久久东京热无码av | 久久久久久av无码免费看大片 | 精品成人av一区二区三区 | av无码不卡在线观看免费 | 亚洲国精产品一二二线 | 亚洲精品国产精品乱码视色 | 久久 国产 尿 小便 嘘嘘 | 亚洲国产日韩a在线播放 | 国产激情精品一区二区三区 | 曰韩少妇内射免费播放 | 老头边吃奶边弄进去呻吟 | 国内精品人妻无码久久久影院蜜桃 | 欧美日韩综合一区二区三区 | 国产人妻精品一区二区三区 | 亚洲国产精品一区二区美利坚 | 亚洲成av人影院在线观看 | 亚洲熟妇色xxxxx欧美老妇 | 国产无遮挡吃胸膜奶免费看 | 一本色道婷婷久久欧美 | 中文字幕无码乱人伦 | 亚洲精品国偷拍自产在线观看蜜桃 | 欧美人与禽猛交狂配 | 亚洲日韩乱码中文无码蜜桃臀网站 | 国产区女主播在线观看 | 精品无码国产一区二区三区av | 嫩b人妻精品一区二区三区 | 日本精品人妻无码免费大全 | 日韩人妻少妇一区二区三区 | 亚洲天堂2017无码 | yw尤物av无码国产在线观看 | 四虎永久在线精品免费网址 | 性色av无码免费一区二区三区 | 亚洲国产欧美国产综合一区 | 亚洲国产综合无码一区 | 欧美成人高清在线播放 | 天堂在线观看www | 青青青爽视频在线观看 | 久久精品国产99久久6动漫 | 成人无码视频在线观看网站 | 青青草原综合久久大伊人精品 | 帮老师解开蕾丝奶罩吸乳网站 | 色综合久久88色综合天天 | 国产美女精品一区二区三区 | 国内少妇偷人精品视频 | 任你躁国产自任一区二区三区 | 国产亚洲精品久久久闺蜜 | 自拍偷自拍亚洲精品被多人伦好爽 | 丝袜足控一区二区三区 | 美女扒开屁股让男人桶 | 无码av免费一区二区三区试看 | 曰本女人与公拘交酡免费视频 | 波多野结衣av在线观看 | 亚洲a无码综合a国产av中文 | 纯爱无遮挡h肉动漫在线播放 | 无码国产激情在线观看 | 国产人妻久久精品二区三区老狼 | 久久亚洲精品中文字幕无男同 | 日韩亚洲欧美中文高清在线 | 免费无码一区二区三区蜜桃大 | 国产一精品一av一免费 | 奇米影视7777久久精品人人爽 | 人人澡人摸人人添 | 久久亚洲精品成人无码 | 窝窝午夜理论片影院 | 99久久久国产精品无码免费 | 中文久久乱码一区二区 | 性欧美疯狂xxxxbbbb | 国产又爽又黄又刺激的视频 | 国产精品18久久久久久麻辣 | 亚洲天堂2017无码中文 | 又紧又大又爽精品一区二区 | 成年美女黄网站色大免费全看 | 狂野欧美激情性xxxx | 欧美日韩视频无码一区二区三 | 国产精品久久国产精品99 | 国产美女极度色诱视频www | 亚洲精品中文字幕久久久久 | 欧美三级a做爰在线观看 | 成人试看120秒体验区 | 女人被男人爽到呻吟的视频 | av在线亚洲欧洲日产一区二区 | 久久这里只有精品视频9 | 波多野结衣乳巨码无在线观看 | 图片小说视频一区二区 | 婷婷综合久久中文字幕蜜桃三电影 | 丰满少妇高潮惨叫视频 | 日日噜噜噜噜夜夜爽亚洲精品 | 欧洲vodafone精品性 | 51国偷自产一区二区三区 | 乌克兰少妇性做爰 | 国产两女互慰高潮视频在线观看 | 红桃av一区二区三区在线无码av | 国产精品99爱免费视频 | 少妇性荡欲午夜性开放视频剧场 | 蜜臀aⅴ国产精品久久久国产老师 | 一个人免费观看的www视频 | 大乳丰满人妻中文字幕日本 | 国产乱码精品一品二品 | 中文字幕av无码一区二区三区电影 | 高潮毛片无遮挡高清免费 | 国产精品毛片一区二区 | 扒开双腿疯狂进出爽爽爽视频 | 欧美喷潮久久久xxxxx | 免费无码的av片在线观看 | 久久久精品欧美一区二区免费 | 日韩欧美中文字幕在线三区 | 丰满妇女强制高潮18xxxx | 欧美xxxxx精品 | 丰满少妇高潮惨叫视频 | 天天摸天天碰天天添 | 国产精品永久免费视频 | 日日天干夜夜狠狠爱 | 99精品国产综合久久久久五月天 | 亚洲熟妇色xxxxx欧美老妇 | 国产内射老熟女aaaa | 久久久婷婷五月亚洲97号色 | 亚洲午夜久久久影院 | 精品久久久无码中文字幕 | 中文字幕久久久久人妻 | 日本va欧美va欧美va精品 | 日本饥渴人妻欲求不满 | 日本一区二区三区免费高清 | 久久精品人妻少妇一区二区三区 | 99国产欧美久久久精品 | 日本丰满护士爆乳xxxx | 精品久久久中文字幕人妻 | 久久五月精品中文字幕 | 鲁一鲁av2019在线 | 国产亚av手机在线观看 | 色欲久久久天天天综合网精品 | 性色欲情网站iwww九文堂 | 人妻无码久久精品人妻 | 国产精品.xx视频.xxtv | 青青草原综合久久大伊人精品 | 亚洲综合精品香蕉久久网 | 欧美成人免费全部网站 | 欧美人妻一区二区三区 | 日日摸夜夜摸狠狠摸婷婷 | 娇妻被黑人粗大高潮白浆 | 国产日产欧产精品精品app | 亚洲中文字幕va福利 | 国产精品.xx视频.xxtv | 中文字幕无码免费久久99 | 98国产精品综合一区二区三区 | 久久精品无码一区二区三区 | 亚洲性无码av中文字幕 | 女人高潮内射99精品 | 亚洲欧洲无卡二区视頻 | 免费观看又污又黄的网站 | aⅴ在线视频男人的天堂 | 女人被爽到呻吟gif动态图视看 | 99麻豆久久久国产精品免费 | 久久国语露脸国产精品电影 | 成人亚洲精品久久久久软件 | 又黄又爽又色的视频 | 欧美人与禽zoz0性伦交 | 国产免费无码一区二区视频 | 久久久www成人免费毛片 | 领导边摸边吃奶边做爽在线观看 | 欧美色就是色 | 中文无码伦av中文字幕 | 九月婷婷人人澡人人添人人爽 | 久久亚洲中文字幕无码 | 最新国产麻豆aⅴ精品无码 | 亚洲精品欧美二区三区中文字幕 | 18精品久久久无码午夜福利 | 国产人妻精品一区二区三区 | 性色欲情网站iwww九文堂 | 欧美xxxx黑人又粗又长 | 蜜桃av抽搐高潮一区二区 | 人妻少妇被猛烈进入中文字幕 | 国产一区二区不卡老阿姨 | 狠狠色欧美亚洲狠狠色www | 久久97精品久久久久久久不卡 | 嫩b人妻精品一区二区三区 | 九九久久精品国产免费看小说 | 精品夜夜澡人妻无码av蜜桃 | 亚洲小说图区综合在线 | 国产内射老熟女aaaa | 欧美日本免费一区二区三区 | 日本一区二区三区免费播放 | 国产三级精品三级男人的天堂 | 国产在线精品一区二区三区直播 | 亚洲精品国产精品乱码视色 | 欧美激情一区二区三区成人 | 帮老师解开蕾丝奶罩吸乳网站 | 国产综合色产在线精品 | 精品国产av色一区二区深夜久久 | 亚洲gv猛男gv无码男同 | 妺妺窝人体色www婷婷 | 丝袜人妻一区二区三区 | 人妻无码久久精品人妻 | 大乳丰满人妻中文字幕日本 | 鲁鲁鲁爽爽爽在线视频观看 | 国精品人妻无码一区二区三区蜜柚 | 又黄又爽又色的视频 | 精品国产一区二区三区av 性色 | 亚洲の无码国产の无码影院 | 少妇无套内谢久久久久 | 国产香蕉尹人综合在线观看 | 久久精品人妻少妇一区二区三区 | 久久人人97超碰a片精品 | 人妻少妇精品无码专区动漫 | 日产国产精品亚洲系列 | 国产午夜精品一区二区三区嫩草 | 精品欧洲av无码一区二区三区 | av人摸人人人澡人人超碰下载 | 免费人成网站视频在线观看 | 国产成人av免费观看 | 国精产品一品二品国精品69xx | 两性色午夜视频免费播放 | 影音先锋中文字幕无码 | 沈阳熟女露脸对白视频 | 综合激情五月综合激情五月激情1 | 在线观看免费人成视频 | 欧美日本精品一区二区三区 | 国产激情艳情在线看视频 | 亚洲欧美日韩国产精品一区二区 | 黑人大群体交免费视频 | 亚洲精品一区二区三区四区五区 | 国产精品永久免费视频 | 中文字幕乱码亚洲无线三区 | 久久精品一区二区三区四区 | 欧美激情综合亚洲一二区 | 一本久道久久综合狠狠爱 | 麻豆国产97在线 | 欧洲 | 久久午夜夜伦鲁鲁片无码免费 | a在线亚洲男人的天堂 | 丁香啪啪综合成人亚洲 | 999久久久国产精品消防器材 | 中文字幕无码av波多野吉衣 | 少妇人妻av毛片在线看 | 中文字幕av伊人av无码av | 麻豆成人精品国产免费 | 国产香蕉尹人综合在线观看 | 成人三级无码视频在线观看 | 在线精品亚洲一区二区 | 99久久99久久免费精品蜜桃 | 国产精华av午夜在线观看 | 亚洲国产高清在线观看视频 | 亚洲性无码av中文字幕 | 日本又色又爽又黄的a片18禁 | 精品 日韩 国产 欧美 视频 | 捆绑白丝粉色jk震动捧喷白浆 | 国产精品内射视频免费 | 国色天香社区在线视频 | 亚洲男人av香蕉爽爽爽爽 | 国内精品人妻无码久久久影院 | 亚洲人成影院在线无码按摩店 | 亚洲精品久久久久久久久久久 | 久久久久se色偷偷亚洲精品av | 天天摸天天碰天天添 | 无码av免费一区二区三区试看 | 国产高清av在线播放 | 久久久久久av无码免费看大片 | 装睡被陌生人摸出水好爽 | 久久久久久久女国产乱让韩 | 亚洲熟妇自偷自拍另类 | 中文字幕色婷婷在线视频 | 性开放的女人aaa片 | 亚洲精品国偷拍自产在线麻豆 | 色一情一乱一伦一区二区三欧美 | 精品水蜜桃久久久久久久 | 国产高清av在线播放 | 国产午夜亚洲精品不卡下载 | 久激情内射婷内射蜜桃人妖 | 无遮挡国产高潮视频免费观看 | 俺去俺来也在线www色官网 | 偷窥村妇洗澡毛毛多 | 国产精品美女久久久网av | 亚洲精品久久久久avwww潮水 | 欧美激情一区二区三区成人 | 国产精品久免费的黄网站 | 欧美日韩视频无码一区二区三 | 任你躁国产自任一区二区三区 | 荡女精品导航 | 麻豆国产丝袜白领秘书在线观看 | 亚洲爆乳大丰满无码专区 | 黑森林福利视频导航 | a片免费视频在线观看 | 亚洲中文字幕无码中文字在线 | 国产内射爽爽大片视频社区在线 | 内射爽无广熟女亚洲 | 在线成人www免费观看视频 | 久久久久久久人妻无码中文字幕爆 | 影音先锋中文字幕无码 | 人人爽人人澡人人人妻 | 97资源共享在线视频 | 免费无码的av片在线观看 | 久久国产36精品色熟妇 | 亚洲毛片av日韩av无码 | 人人爽人人澡人人人妻 | 粗大的内捧猛烈进出视频 | 欧美xxxxx精品 | 国产黑色丝袜在线播放 | 97se亚洲精品一区 | 狠狠色欧美亚洲狠狠色www | 女人高潮内射99精品 | 国产精品久久久久久亚洲毛片 | 日本精品久久久久中文字幕 | 亚洲日韩av一区二区三区中文 | 亚洲成av人片在线观看无码不卡 | 少妇太爽了在线观看 | 中国大陆精品视频xxxx | 国产xxx69麻豆国语对白 | 久久五月精品中文字幕 | 国产性生大片免费观看性 | 精品欧洲av无码一区二区三区 | 久久zyz资源站无码中文动漫 | 国产在线无码精品电影网 | 久久亚洲精品成人无码 | 久久久久人妻一区精品色欧美 | 天天综合网天天综合色 | 人人妻在人人 | 精品人妻人人做人人爽 | 国语自产偷拍精品视频偷 | 一本加勒比波多野结衣 | 亚洲日韩av一区二区三区四区 | 精品无码av一区二区三区 | 亚洲色大成网站www国产 | 99精品久久毛片a片 | 久久久精品人妻久久影视 | 国产综合在线观看 | 牲欲强的熟妇农村老妇女视频 | 国产女主播喷水视频在线观看 | 亚洲色欲色欲欲www在线 | 精品日本一区二区三区在线观看 | 亚洲色欲久久久综合网东京热 | 色综合天天综合狠狠爱 | 高清国产亚洲精品自在久久 | 日韩精品无码一区二区中文字幕 | aⅴ亚洲 日韩 色 图网站 播放 | 国产成人无码区免费内射一片色欲 | 国产成人精品无码播放 | 日本成熟视频免费视频 | 国产精品美女久久久网av | 中文字幕人成乱码熟女app | 欧美性生交活xxxxxdddd | 日韩 欧美 动漫 国产 制服 | 亚洲精品久久久久avwww潮水 | 国产suv精品一区二区五 | 成人一在线视频日韩国产 | 国产美女精品一区二区三区 | 97久久国产亚洲精品超碰热 | 中文字幕日产无线码一区 | 亚洲日本一区二区三区在线 | 久久精品成人欧美大片 | 亚洲区小说区激情区图片区 | 欧美老妇与禽交 | 玩弄少妇高潮ⅹxxxyw | 国产亚洲视频中文字幕97精品 | 亚洲乱码中文字幕在线 | 精品无码成人片一区二区98 | 精品无码国产一区二区三区av | 久久久久久av无码免费看大片 | 青春草在线视频免费观看 | 亚洲一区二区三区在线观看网站 | 国产亚洲精品久久久ai换 | 一个人看的www免费视频在线观看 | 大地资源网第二页免费观看 | 亚洲国产精华液网站w | 精品国产麻豆免费人成网站 | 中文亚洲成a人片在线观看 | 最近免费中文字幕中文高清百度 | 久久99精品久久久久婷婷 | 国产免费无码一区二区视频 | 好爽又高潮了毛片免费下载 | 成人精品视频一区二区三区尤物 | 爱做久久久久久 | 国精品人妻无码一区二区三区蜜柚 | 麻豆国产人妻欲求不满谁演的 | 日本丰满护士爆乳xxxx | 中文字幕av无码一区二区三区电影 | 国产精品99久久精品爆乳 | 国产精品亚洲综合色区韩国 | 精品日本一区二区三区在线观看 | 亚洲天堂2017无码中文 | 中国女人内谢69xxxx | 内射后入在线观看一区 | 精品夜夜澡人妻无码av蜜桃 | 国产又爽又黄又刺激的视频 | aa片在线观看视频在线播放 | 激情综合激情五月俺也去 | 国产精品人人爽人人做我的可爱 | 精品日本一区二区三区在线观看 | 熟女少妇在线视频播放 | 欧美精品国产综合久久 | 麻豆国产丝袜白领秘书在线观看 | 3d动漫精品啪啪一区二区中 | 极品嫩模高潮叫床 | 无码中文字幕色专区 | 波多野结衣 黑人 | 久久人人爽人人爽人人片av高清 | 天堂亚洲2017在线观看 | 少妇性荡欲午夜性开放视频剧场 | 人妻少妇被猛烈进入中文字幕 | 男人和女人高潮免费网站 | 亚洲精品一区三区三区在线观看 | 日韩人妻无码中文字幕视频 | 色欲综合久久中文字幕网 | 一本久久a久久精品亚洲 | 久久午夜夜伦鲁鲁片无码免费 | 欧美老妇交乱视频在线观看 | 人妻与老人中文字幕 | 一本久道久久综合狠狠爱 | 激情综合激情五月俺也去 | 一本大道久久东京热无码av | 久久久久免费精品国产 | 夜先锋av资源网站 | 图片小说视频一区二区 | 亚洲人成网站在线播放942 | 无码人妻av免费一区二区三区 | 国产在线精品一区二区高清不卡 | 日日天日日夜日日摸 | v一区无码内射国产 | 国产精品久久久午夜夜伦鲁鲁 | 真人与拘做受免费视频一 | 午夜免费福利小电影 | 理论片87福利理论电影 | 丰满护士巨好爽好大乳 | 国产精品久久久久无码av色戒 | 国产午夜手机精彩视频 | 国产另类ts人妖一区二区 | 久久久久se色偷偷亚洲精品av | 国产 精品 自在自线 | 少妇厨房愉情理9仑片视频 | 国产成人一区二区三区别 | 国产精品久久久久久亚洲影视内衣 | 综合激情五月综合激情五月激情1 | 美女黄网站人色视频免费国产 | 国产又粗又硬又大爽黄老大爷视 | 亚洲精品国偷拍自产在线麻豆 | 免费看男女做好爽好硬视频 | 亚洲精品鲁一鲁一区二区三区 | 欧美xxxx黑人又粗又长 | 强辱丰满人妻hd中文字幕 | 亚洲娇小与黑人巨大交 | 精品国产国产综合精品 | 日韩亚洲欧美中文高清在线 | 亚洲中文字幕乱码av波多ji | 国产特级毛片aaaaaaa高清 | 欧美大屁股xxxxhd黑色 | 欧洲美熟女乱又伦 | 曰本女人与公拘交酡免费视频 | 欧美黑人性暴力猛交喷水 | 又大又硬又爽免费视频 | 日本欧美一区二区三区乱码 | 国产色视频一区二区三区 | 4hu四虎永久在线观看 | 久久国语露脸国产精品电影 | 国产精品无码久久av | 东京热一精品无码av | 国产极品美女高潮无套在线观看 | 国产欧美精品一区二区三区 | 亚洲国产精品久久久天堂 | 欧美黑人巨大xxxxx | 九九热爱视频精品 | 少妇高潮一区二区三区99 | 波多野结衣aⅴ在线 | 国产激情无码一区二区 | 99精品视频在线观看免费 | 免费乱码人妻系列无码专区 | 午夜无码人妻av大片色欲 | 亚洲s码欧洲m码国产av | 国产人妻精品一区二区三区不卡 | 国产婷婷色一区二区三区在线 | 无码吃奶揉捏奶头高潮视频 | 蜜桃视频插满18在线观看 | 正在播放老肥熟妇露脸 | 四虎国产精品免费久久 | 久激情内射婷内射蜜桃人妖 | 亚洲午夜福利在线观看 | 国产做国产爱免费视频 | 日本高清一区免费中文视频 | 国产高清不卡无码视频 | 欧美人与牲动交xxxx | 日韩人妻系列无码专区 | 中文字幕无线码免费人妻 | 国产偷国产偷精品高清尤物 | 久久精品无码一区二区三区 | 国产午夜福利100集发布 | 国产偷国产偷精品高清尤物 | 日本一卡二卡不卡视频查询 | 久久久精品国产sm最大网站 | 色欲综合久久中文字幕网 | 无码人妻精品一区二区三区不卡 | 精品偷拍一区二区三区在线看 | 久久久久人妻一区精品色欧美 | 国产精品鲁鲁鲁 | 丰满少妇熟乱xxxxx视频 | 国产亚洲欧美日韩亚洲中文色 | 永久免费观看美女裸体的网站 | 300部国产真实乱 | 精品无人国产偷自产在线 | 国内精品九九久久久精品 | 性开放的女人aaa片 | 久久久久人妻一区精品色欧美 | 在线精品亚洲一区二区 | 国内揄拍国内精品人妻 | 国产农村乱对白刺激视频 | 成人精品一区二区三区中文字幕 | 蜜桃av蜜臀av色欲av麻 999久久久国产精品消防器材 | 午夜福利不卡在线视频 | 亚洲精品成人av在线 | 精品夜夜澡人妻无码av蜜桃 | 领导边摸边吃奶边做爽在线观看 | 99久久亚洲精品无码毛片 | 美女扒开屁股让男人桶 | 中文毛片无遮挡高清免费 | 97久久精品无码一区二区 | 亚洲综合在线一区二区三区 | 成人aaa片一区国产精品 | 亚洲中文字幕无码一久久区 | 老熟妇乱子伦牲交视频 | 樱花草在线社区www | 国产成人综合在线女婷五月99播放 | 亚洲色偷偷偷综合网 | 国产人成高清在线视频99最全资源 | 波多野结衣乳巨码无在线观看 | 宝宝好涨水快流出来免费视频 | 99久久人妻精品免费二区 | 色欲综合久久中文字幕网 | 久久久久se色偷偷亚洲精品av | 久久综合久久自在自线精品自 | 国产乱人无码伦av在线a | 欧美老妇交乱视频在线观看 | 在线观看国产午夜福利片 | 国产精品久久久午夜夜伦鲁鲁 | 男女猛烈xx00免费视频试看 | 久久久久久国产精品无码下载 | 狠狠色欧美亚洲狠狠色www | 玩弄人妻少妇500系列视频 | 亚洲熟妇自偷自拍另类 | 久久久精品国产sm最大网站 | 一区二区三区乱码在线 | 欧洲 | 在线观看免费人成视频 | 久久99精品国产.久久久久 | 又粗又大又硬又长又爽 | 正在播放东北夫妻内射 | 性做久久久久久久久 | 无码国模国产在线观看 | 久久国产精品精品国产色婷婷 | 国产精品内射视频免费 | 人人妻人人澡人人爽欧美精品 | 人人妻人人澡人人爽欧美一区 | aa片在线观看视频在线播放 | 狠狠噜狠狠狠狠丁香五月 | 亚洲欧美色中文字幕在线 | 无码中文字幕色专区 | 久久精品国产精品国产精品污 | 国产农村乱对白刺激视频 | 精品人人妻人人澡人人爽人人 | 国产亚洲精品久久久闺蜜 | 久久综合激激的五月天 | 国产午夜福利100集发布 | 日本精品人妻无码免费大全 | 成人影院yy111111在线观看 | 精品人妻人人做人人爽夜夜爽 | 欧美国产亚洲日韩在线二区 | 国产人妻久久精品二区三区老狼 | 天堂а√在线地址中文在线 | 又大又黄又粗又爽的免费视频 | 欧美国产日产一区二区 | 国内精品久久久久久中文字幕 | 日日摸天天摸爽爽狠狠97 | 男女下面进入的视频免费午夜 | 亚洲国产高清在线观看视频 | 人人妻在人人 | 亚洲欧美精品aaaaaa片 | 中文字幕 亚洲精品 第1页 | 国产精品亚洲五月天高清 | 欧美人与善在线com | 麻豆果冻传媒2021精品传媒一区下载 | 精品 日韩 国产 欧美 视频 | 国产亚洲日韩欧美另类第八页 | 一个人免费观看的www视频 | 国产suv精品一区二区五 | 六十路熟妇乱子伦 | 日韩亚洲欧美精品综合 | 一区二区传媒有限公司 | 日本乱人伦片中文三区 | 亚洲欧美日韩国产精品一区二区 | 无码国产色欲xxxxx视频 | 久久综合色之久久综合 | 中文字幕乱码人妻无码久久 | 久久久婷婷五月亚洲97号色 | 色老头在线一区二区三区 | 欧美放荡的少妇 | 亚洲成熟女人毛毛耸耸多 | 无码吃奶揉捏奶头高潮视频 | 国产精品免费大片 | 伊在人天堂亚洲香蕉精品区 | 欧洲熟妇精品视频 | 桃花色综合影院 | 亚无码乱人伦一区二区 | 中文字幕av日韩精品一区二区 | 久久综合网欧美色妞网 | 中文字幕无码av波多野吉衣 | aa片在线观看视频在线播放 | 国产亚洲精品久久久久久久久动漫 | 性欧美大战久久久久久久 | 少妇性l交大片欧洲热妇乱xxx | 丝袜足控一区二区三区 | 久久天天躁夜夜躁狠狠 | 高清国产亚洲精品自在久久 | 在线视频网站www色 | 天干天干啦夜天干天2017 | 少妇太爽了在线观看 | 一区二区传媒有限公司 | 久久人人97超碰a片精品 | 亚洲国产精品久久人人爱 | 蜜桃av抽搐高潮一区二区 | 亚洲无人区午夜福利码高清完整版 | 一本久道高清无码视频 | 任你躁在线精品免费 | 色综合久久久无码网中文 | 久久午夜无码鲁丝片秋霞 | 亚洲国产精品久久久久久 | 内射爽无广熟女亚洲 | 无套内谢的新婚少妇国语播放 | 日本欧美一区二区三区乱码 | 三级4级全黄60分钟 | 亚洲精品一区二区三区四区五区 | 少妇性荡欲午夜性开放视频剧场 | 狠狠色噜噜狠狠狠狠7777米奇 | 无码av岛国片在线播放 | 高清无码午夜福利视频 | 3d动漫精品啪啪一区二区中 | 樱花草在线播放免费中文 | 国产一精品一av一免费 | 久久99热只有频精品8 | 日本熟妇乱子伦xxxx | 国产成人无码a区在线观看视频app | 亚洲欧洲日本无在线码 | 国产凸凹视频一区二区 | 国产精品亚洲lv粉色 | 国产精品a成v人在线播放 | 久久99精品国产.久久久久 | 亚洲欧洲中文日韩av乱码 | 欧美阿v高清资源不卡在线播放 | 日日鲁鲁鲁夜夜爽爽狠狠 | 2020久久超碰国产精品最新 | 男女爱爱好爽视频免费看 | 伊人久久婷婷五月综合97色 | 亚洲一区二区三区国产精华液 | 久久五月精品中文字幕 | 人妻少妇精品无码专区二区 | 欧美日韩亚洲国产精品 | 久久亚洲中文字幕精品一区 | 国产精品久久久av久久久 | 国产精品久久久一区二区三区 | 天堂无码人妻精品一区二区三区 | 黑森林福利视频导航 | 正在播放老肥熟妇露脸 | 97久久精品无码一区二区 | 成人影院yy111111在线观看 | 亚洲国产精品无码久久久久高潮 | 亚洲日韩乱码中文无码蜜桃臀网站 | 久久综合激激的五月天 | 色爱情人网站 | 人妻少妇精品无码专区动漫 | 国产成人综合在线女婷五月99播放 | 国产精品无码永久免费888 | а√天堂www在线天堂小说 | 亚洲国产精品久久久天堂 | 精品久久综合1区2区3区激情 | 蜜臀av无码人妻精品 | 老司机亚洲精品影院无码 | 亚洲人成网站色7799 | 国产乱人伦app精品久久 国产在线无码精品电影网 国产国产精品人在线视 | www国产精品内射老师 | 特级做a爰片毛片免费69 | 高清国产亚洲精品自在久久 | 亚洲精品无码国产 | 欧美性生交活xxxxxdddd | 中文字幕无码人妻少妇免费 | 亚洲欧洲日本无在线码 | 亚洲国产精品成人久久蜜臀 | 国产成人精品一区二区在线小狼 | 中文毛片无遮挡高清免费 | 欧美熟妇另类久久久久久多毛 | 人妻少妇精品视频专区 | 久久久精品人妻久久影视 | 色综合久久中文娱乐网 | 国产精品亚洲lv粉色 | 18黄暴禁片在线观看 | 欧美熟妇另类久久久久久多毛 | 99在线 | 亚洲 | 少妇人妻av毛片在线看 | 人人超人人超碰超国产 | 久久亚洲中文字幕精品一区 | 国产精品国产三级国产专播 | 国产偷自视频区视频 | 激情五月综合色婷婷一区二区 | 97se亚洲精品一区 | 色综合久久88色综合天天 | 亚洲色欲色欲欲www在线 | 精品无码成人片一区二区98 | 精品一区二区不卡无码av | 国产精品.xx视频.xxtv | 正在播放东北夫妻内射 | 欧洲欧美人成视频在线 | 自拍偷自拍亚洲精品被多人伦好爽 | 又粗又大又硬毛片免费看 | 色一情一乱一伦一视频免费看 | 久久精品国产99久久6动漫 | 久热国产vs视频在线观看 | 波多野结衣乳巨码无在线观看 | 亚洲一区二区三区无码久久 | 欧美人与禽zoz0性伦交 | 啦啦啦www在线观看免费视频 | 中国女人内谢69xxxxxa片 | 成人精品视频一区二区三区尤物 | 综合激情五月综合激情五月激情1 | 99国产欧美久久久精品 | 最新国产麻豆aⅴ精品无码 | 伊人久久大香线蕉亚洲 | 美女极度色诱视频国产 | 久久久久亚洲精品男人的天堂 | 玩弄少妇高潮ⅹxxxyw | 日韩精品无码免费一区二区三区 | 亚洲综合精品香蕉久久网 | 亚洲欧美国产精品专区久久 | 国产小呦泬泬99精品 | 国产真人无遮挡作爱免费视频 | 波多野结衣av一区二区全免费观看 | 中文字幕无码人妻少妇免费 | 中文字幕久久久久人妻 | 伊人久久大香线蕉午夜 | 天下第一社区视频www日本 | 熟女体下毛毛黑森林 | 中文字幕无码乱人伦 | 国产绳艺sm调教室论坛 | 漂亮人妻洗澡被公强 日日躁 | 4hu四虎永久在线观看 | 九九在线中文字幕无码 | 国产亚洲精品久久久闺蜜 | 日韩精品无码一本二本三本色 | 日韩人妻无码一区二区三区久久99 | 亚洲精品一区三区三区在线观看 | 欧美猛少妇色xxxxx | 日本欧美一区二区三区乱码 | 正在播放东北夫妻内射 | 青青久在线视频免费观看 | 人妻aⅴ无码一区二区三区 | 日日噜噜噜噜夜夜爽亚洲精品 | 久久精品国产日本波多野结衣 | 国产另类ts人妖一区二区 | 成熟妇人a片免费看网站 | 国产精品18久久久久久麻辣 | 76少妇精品导航 | 人妻无码久久精品人妻 | 亚洲精品中文字幕乱码 | 国产成人无码专区 | 在线视频网站www色 | av人摸人人人澡人人超碰下载 | 国产在线一区二区三区四区五区 | 少妇人妻av毛片在线看 | 欧美 丝袜 自拍 制服 另类 | 亚洲午夜久久久影院 | 亚洲日本va中文字幕 | 国产精华av午夜在线观看 | 性开放的女人aaa片 | 国产亚洲视频中文字幕97精品 | 久久精品国产一区二区三区 | 国产激情艳情在线看视频 | 中文字幕无码日韩专区 | 婷婷丁香六月激情综合啪 | 国产精品成人av在线观看 | 国产精品丝袜黑色高跟鞋 | 久久 国产 尿 小便 嘘嘘 | 欧洲精品码一区二区三区免费看 | 国产一区二区三区日韩精品 | 亚洲成a人一区二区三区 | 国内精品久久久久久中文字幕 | 免费无码午夜福利片69 | 午夜男女很黄的视频 | 中文字幕无码日韩专区 | 又大又硬又黄的免费视频 | 思思久久99热只有频精品66 | 国产网红无码精品视频 | 国产亚洲美女精品久久久2020 | 又粗又大又硬又长又爽 | 久久精品国产大片免费观看 | 午夜肉伦伦影院 | 又黄又爽又色的视频 | 精品国产aⅴ无码一区二区 | 免费人成网站视频在线观看 | 国产av久久久久精东av | 国产av无码专区亚洲a∨毛片 | 97久久超碰中文字幕 | 免费中文字幕日韩欧美 | 国产又粗又硬又大爽黄老大爷视 | 久久精品国产一区二区三区 | √天堂资源地址中文在线 | 亚洲成av人片天堂网无码】 | 欧美三级不卡在线观看 | 国产精品久久久久无码av色戒 | 亚洲熟妇色xxxxx亚洲 | 日韩av无码一区二区三区不卡 | 国产精品久久久久久无码 | 欧美性黑人极品hd | 中文字幕人妻无码一夲道 | 欧美日韩久久久精品a片 | 久久综合网欧美色妞网 | 一本无码人妻在中文字幕免费 | 67194成是人免费无码 | 最新版天堂资源中文官网 | 亚洲国精产品一二二线 | 男人扒开女人内裤强吻桶进去 | 久久久国产一区二区三区 | 亚洲色在线无码国产精品不卡 | 亚洲欧洲日本综合aⅴ在线 | 中文精品无码中文字幕无码专区 | 天堂一区人妻无码 | 天堂а√在线地址中文在线 | 国产国产精品人在线视 | 久久zyz资源站无码中文动漫 | 一本精品99久久精品77 | 中文字幕无码av激情不卡 | 久久久精品欧美一区二区免费 | 国内综合精品午夜久久资源 | 亚洲精品国产精品乱码不卡 | 色窝窝无码一区二区三区色欲 | 午夜精品久久久久久久 | 国产熟妇高潮叫床视频播放 | 欧美日韩亚洲国产精品 | 樱花草在线播放免费中文 | 久久久久久av无码免费看大片 | 午夜无码人妻av大片色欲 | 永久免费观看美女裸体的网站 | 人人妻人人澡人人爽人人精品浪潮 | 无码av中文字幕免费放 | 欧美日韩人成综合在线播放 | 色婷婷综合激情综在线播放 | 在线成人www免费观看视频 | 乱人伦人妻中文字幕无码 | 亚洲熟女一区二区三区 | 波多野结衣高清一区二区三区 | 白嫩日本少妇做爰 | 中文字幕人妻无码一夲道 | 无码人妻丰满熟妇区五十路百度 | 日本在线高清不卡免费播放 | 狠狠色色综合网站 | 亚拍精品一区二区三区探花 | 99精品久久毛片a片 | 清纯唯美经典一区二区 | 精品人妻中文字幕有码在线 | 鲁大师影院在线观看 | 俺去俺来也在线www色官网 | 中文亚洲成a人片在线观看 | 麻豆人妻少妇精品无码专区 | 亚洲狠狠婷婷综合久久 | 狂野欧美性猛xxxx乱大交 | 欧美兽交xxxx×视频 | 国产亚av手机在线观看 | 国产内射爽爽大片视频社区在线 | 丝袜 中出 制服 人妻 美腿 | 亚洲精品一区二区三区在线观看 | 强奷人妻日本中文字幕 | 亚洲一区二区三区在线观看网站 | 天堂一区人妻无码 | 天海翼激烈高潮到腰振不止 | 国产精品嫩草久久久久 | 亚洲爆乳精品无码一区二区三区 | 成人欧美一区二区三区 | 久久无码中文字幕免费影院蜜桃 | 人人妻人人澡人人爽精品欧美 | 精品国产av色一区二区深夜久久 | 日本xxxx色视频在线观看免费 | 麻豆精产国品 | 午夜无码区在线观看 | 免费观看又污又黄的网站 | 男女性色大片免费网站 | 99久久精品国产一区二区蜜芽 | 亚洲中文字幕无码中文字在线 | 亚欧洲精品在线视频免费观看 | 麻豆国产人妻欲求不满 | 国产成人无码区免费内射一片色欲 | 久久综合久久自在自线精品自 | 国产精品久久久久久久9999 | 无码乱肉视频免费大全合集 | 久久99精品国产麻豆蜜芽 | 好爽又高潮了毛片免费下载 | 欧洲vodafone精品性 | 久久亚洲精品中文字幕无男同 | 无码av最新清无码专区吞精 | 特级做a爰片毛片免费69 | 一本色道久久综合亚洲精品不卡 | 俄罗斯老熟妇色xxxx | 成年美女黄网站色大免费视频 | 蜜臀av在线播放 久久综合激激的五月天 | 久久99精品国产.久久久久 | 欧美野外疯狂做受xxxx高潮 | 亚洲精品午夜无码电影网 | 色五月丁香五月综合五月 | 亚洲精品一区三区三区在线观看 | 99久久久国产精品无码免费 | 国内揄拍国内精品人妻 | 成人免费无码大片a毛片 | 97久久国产亚洲精品超碰热 | 国产精品久免费的黄网站 | 大色综合色综合网站 | 日本护士xxxxhd少妇 | 无码任你躁久久久久久久 | 鲁一鲁av2019在线 | 色婷婷综合中文久久一本 | 国产精品va在线播放 | 又大又硬又黄的免费视频 | 少妇高潮喷潮久久久影院 | 欧美日本免费一区二区三区 | 色综合久久久久综合一本到桃花网 | 久久久久久a亚洲欧洲av冫 | 图片小说视频一区二区 | 久久综合九色综合欧美狠狠 | 色噜噜亚洲男人的天堂 | 亲嘴扒胸摸屁股激烈网站 | 国产精品久久久久久亚洲影视内衣 | 97久久精品无码一区二区 | 日韩精品成人一区二区三区 | 亚洲精品国产精品乱码视色 | 秋霞成人午夜鲁丝一区二区三区 | 国产精品对白交换视频 | 又粗又大又硬又长又爽 | 国产偷国产偷精品高清尤物 | 亚洲人成无码网www | 国产无av码在线观看 | 成人影院yy111111在线观看 | 兔费看少妇性l交大片免费 | 偷窥日本少妇撒尿chinese | yw尤物av无码国产在线观看 | 久久综合九色综合97网 | 亚洲国产精品美女久久久久 | 51国偷自产一区二区三区 | 国产成人亚洲综合无码 | 久久www免费人成人片 | 2020最新国产自产精品 | 成 人影片 免费观看 | 人妻中文无码久热丝袜 | 狠狠色欧美亚洲狠狠色www | 无码人妻丰满熟妇区毛片18 | 国产av久久久久精东av | 日日天日日夜日日摸 | 欧美日韩综合一区二区三区 | 国产三级精品三级男人的天堂 | 欧美 丝袜 自拍 制服 另类 | 国内精品人妻无码久久久影院 | 欧美高清在线精品一区 | 老司机亚洲精品影院无码 | 精品国产青草久久久久福利 | 久久精品99久久香蕉国产色戒 | 亚洲一区二区三区在线观看网站 | 亚洲精品一区二区三区婷婷月 | 午夜福利一区二区三区在线观看 | 国产人妻精品一区二区三区 | 亚洲熟熟妇xxxx | 国产乱子伦视频在线播放 | 性生交片免费无码看人 | 在教室伦流澡到高潮hnp视频 | 亚洲国产欧美国产综合一区 | 亚洲中文字幕av在天堂 | 成人动漫在线观看 | 在线观看欧美一区二区三区 | 免费观看激色视频网站 | 又湿又紧又大又爽a视频国产 | 黑人巨大精品欧美黑寡妇 | 中国大陆精品视频xxxx | 国产黄在线观看免费观看不卡 | 亚洲精品一区三区三区在线观看 | 欧美 日韩 人妻 高清 中文 | 中文字幕无码日韩专区 | 亚洲经典千人经典日产 | 午夜福利电影 | 成人毛片一区二区 | 爽爽影院免费观看 | 伊人久久婷婷五月综合97色 | 强开小婷嫩苞又嫩又紧视频 | 99er热精品视频 | 国产农村乱对白刺激视频 | 日日噜噜噜噜夜夜爽亚洲精品 | 久久午夜夜伦鲁鲁片无码免费 | 日本一卡2卡3卡4卡无卡免费网站 国产一区二区三区影院 | 永久免费观看美女裸体的网站 | 伊人久久大香线蕉av一区二区 | 青春草在线视频免费观看 | 日本欧美一区二区三区乱码 | 女高中生第一次破苞av | 日韩精品无码一区二区中文字幕 | 欧洲精品码一区二区三区免费看 | 国产肉丝袜在线观看 | 天天燥日日燥 | 国产成人精品三级麻豆 | 亚洲欧美日韩综合久久久 | 无码av免费一区二区三区试看 | 日本又色又爽又黄的a片18禁 | 东京无码熟妇人妻av在线网址 | 国产绳艺sm调教室论坛 | 中文字幕无码免费久久99 | 亚洲精品美女久久久久久久 | 88国产精品欧美一区二区三区 | 人人澡人人透人人爽 | 国产福利视频一区二区 | 强开小婷嫩苞又嫩又紧视频 | 日本一区二区三区免费播放 | 精品无人国产偷自产在线 | 丰满人妻被黑人猛烈进入 | 国产综合久久久久鬼色 | 沈阳熟女露脸对白视频 | 成人三级无码视频在线观看 | 色情久久久av熟女人妻网站 | 成人精品视频一区二区 | aⅴ在线视频男人的天堂 | 国产亚洲精品久久久久久 | 精品久久久久久亚洲精品 | a国产一区二区免费入口 | 欧洲熟妇精品视频 | 久久国产精品萌白酱免费 | 亚洲伊人久久精品影院 | 国产97色在线 | 免 | 麻豆精品国产精华精华液好用吗 | 精品国产一区二区三区四区在线看 | 久久午夜无码鲁丝片秋霞 | 国产亚洲美女精品久久久2020 | 久久亚洲日韩精品一区二区三区 | 国产特级毛片aaaaaaa高清 | 国内精品人妻无码久久久影院蜜桃 | www国产亚洲精品久久久日本 | 蜜桃av抽搐高潮一区二区 | 亚洲成a人片在线观看无码3d | 国产香蕉97碰碰久久人人 | 无遮挡国产高潮视频免费观看 | 狂野欧美激情性xxxx | 日韩精品乱码av一区二区 | 性欧美大战久久久久久久 | 中文字幕乱码亚洲无线三区 | 国产国产精品人在线视 | 日韩视频 中文字幕 视频一区 | 精品成在人线av无码免费看 | 成人精品视频一区二区 | 无码av中文字幕免费放 | 国产精品第一区揄拍无码 | 日本熟妇大屁股人妻 | 97精品人妻一区二区三区香蕉 | 特大黑人娇小亚洲女 | 性啪啪chinese东北女人 | 人人妻人人澡人人爽精品欧美 | 国产精品亚洲五月天高清 | 精品久久8x国产免费观看 | 久久亚洲精品中文字幕无男同 | 亚洲成a人片在线观看无码 | 久久久久久久女国产乱让韩 | 免费观看又污又黄的网站 | 国产乱人伦app精品久久 国产在线无码精品电影网 国产国产精品人在线视 | 少妇太爽了在线观看 | 1000部夫妻午夜免费 | 久久久精品人妻久久影视 | 久久综合狠狠综合久久综合88 | 国产熟女一区二区三区四区五区 | 日本精品人妻无码77777 天堂一区人妻无码 | 亚洲欧美日韩成人高清在线一区 | 色情久久久av熟女人妻网站 | 乱人伦人妻中文字幕无码 | 欧美亚洲日韩国产人成在线播放 | 欧美xxxxx精品 | 狠狠躁日日躁夜夜躁2020 | 伊人久久婷婷五月综合97色 | 国产乱人伦偷精品视频 | 国产精品久久国产三级国 | 18禁黄网站男男禁片免费观看 | 国产精品高潮呻吟av久久 | 欧美性色19p | 亚洲大尺度无码无码专区 | 131美女爱做视频 | 精品国产精品久久一区免费式 | 国产97人人超碰caoprom | 国精品人妻无码一区二区三区蜜柚 | 中文字幕中文有码在线 | 俺去俺来也在线www色官网 | 一个人看的www免费视频在线观看 | 九九综合va免费看 | 久久久久免费精品国产 | 97久久国产亚洲精品超碰热 | 国产熟妇另类久久久久 | 又大又紧又粉嫩18p少妇 | 亚洲中文字幕无码中字 | 性生交大片免费看l | 无码成人精品区在线观看 | 国产亚洲精品久久久久久 | 亚洲成av人综合在线观看 | 欧美性生交活xxxxxdddd | 爆乳一区二区三区无码 | 日韩亚洲欧美中文高清在线 | 精品一区二区三区无码免费视频 | 国产一区二区不卡老阿姨 | 欧美激情内射喷水高潮 | 欧美精品国产综合久久 | aⅴ在线视频男人的天堂 | 蜜桃av抽搐高潮一区二区 | 国产精品久久国产精品99 | 无码乱肉视频免费大全合集 | 激情五月综合色婷婷一区二区 | 超碰97人人做人人爱少妇 | 日韩精品一区二区av在线 | 九九久久精品国产免费看小说 | 18禁止看的免费污网站 | 日本大香伊一区二区三区 | 日本一卡2卡3卡四卡精品网站 | 无套内谢的新婚少妇国语播放 | 亚洲色欲久久久综合网东京热 | 亚洲熟妇色xxxxx欧美老妇y | 97精品人妻一区二区三区香蕉 | 免费国产成人高清在线观看网站 | 99久久99久久免费精品蜜桃 | 日本丰满护士爆乳xxxx | 在线天堂新版最新版在线8 | 亚洲国产日韩a在线播放 | 国产午夜亚洲精品不卡 | 色五月五月丁香亚洲综合网 | 国产精品第一区揄拍无码 | 亚洲国产高清在线观看视频 | 女人被男人躁得好爽免费视频 | 欧美兽交xxxx×视频 | 狂野欧美性猛交免费视频 | 亚洲中文无码av永久不收费 | 成人女人看片免费视频放人 | 亚洲精品一区三区三区在线观看 | 麻花豆传媒剧国产免费mv在线 | 性欧美videos高清精品 | 久久www免费人成人片 | 无码国产乱人伦偷精品视频 | 亚洲性无码av中文字幕 | 国产内射老熟女aaaa | 国产亚洲精品久久久ai换 | 午夜熟女插插xx免费视频 | 亚洲精品无码人妻无码 | 亚洲aⅴ无码成人网站国产app | 日韩人妻少妇一区二区三区 | 亚洲区欧美区综合区自拍区 | 婷婷五月综合缴情在线视频 | 成年美女黄网站色大免费全看 | 国产极品美女高潮无套在线观看 | 色婷婷综合中文久久一本 | 国产精品爱久久久久久久 | 樱花草在线社区www | 国产精品理论片在线观看 | 欧美性猛交内射兽交老熟妇 | 欧美日本免费一区二区三区 | 久久这里只有精品视频9 | 九月婷婷人人澡人人添人人爽 | 中文无码精品a∨在线观看不卡 | 波多野结衣aⅴ在线 | 精品人妻人人做人人爽 | 女人高潮内射99精品 | 中文字幕人妻无码一夲道 | 女人被爽到呻吟gif动态图视看 | 国产精品嫩草久久久久 | 国产性猛交╳xxx乱大交 国产精品久久久久久无码 欧洲欧美人成视频在线 | 国产成人午夜福利在线播放 | 国产精品自产拍在线观看 | 欧美精品一区二区精品久久 | 色老头在线一区二区三区 | 一本大道久久东京热无码av | 在线成人www免费观看视频 | 亚洲a无码综合a国产av中文 | 免费国产成人高清在线观看网站 | 中文字幕日韩精品一区二区三区 | 国产无遮挡又黄又爽免费视频 | www国产亚洲精品久久久日本 | 麻豆果冻传媒2021精品传媒一区下载 | 亚洲欧美国产精品专区久久 | 无码一区二区三区在线观看 | 亚洲呦女专区 | 色综合久久久无码中文字幕 | 亚洲一区二区三区四区 | 亚洲成av人综合在线观看 | 国产免费久久久久久无码 | 国产9 9在线 | 中文 | 久久久中文久久久无码 | 久久久中文字幕日本无吗 | 亚洲自偷自拍另类第1页 | 国产精品亚洲专区无码不卡 | 久久精品女人的天堂av | 国产九九九九九九九a片 | 乱中年女人伦av三区 | 一个人看的视频www在线 | 永久免费观看美女裸体的网站 | 四虎永久在线精品免费网址 | 亚洲国产av美女网站 | 自拍偷自拍亚洲精品10p | 国产成人综合色在线观看网站 | 久久久久久a亚洲欧洲av冫 | 又色又爽又黄的美女裸体网站 | 精品无码一区二区三区爱欲 | 国产精品亚洲一区二区三区喷水 | 18禁黄网站男男禁片免费观看 | 亚洲一区二区三区无码久久 | 嫩b人妻精品一区二区三区 | 波多野结衣乳巨码无在线观看 | 亚洲成a人片在线观看日本 | 伊人久久婷婷五月综合97色 | 好屌草这里只有精品 | 婷婷五月综合激情中文字幕 | 午夜理论片yy44880影院 | 在线a亚洲视频播放在线观看 | 一区二区传媒有限公司 | 亚洲欧美日韩成人高清在线一区 | 亚洲国产精品久久人人爱 | 377p欧洲日本亚洲大胆 | 精品无人国产偷自产在线 | 人妻与老人中文字幕 | 国产精品香蕉在线观看 | 欧美激情一区二区三区成人 | 男女猛烈xx00免费视频试看 | 欧美日韩视频无码一区二区三 | 国产激情无码一区二区app | 亚洲乱码中文字幕在线 | 国产精品视频免费播放 | 在线 国产 欧美 亚洲 天堂 | 自拍偷自拍亚洲精品被多人伦好爽 | 伊人久久大香线焦av综合影院 | 欧美日韩一区二区三区自拍 | 国产性猛交╳xxx乱大交 国产精品久久久久久无码 欧洲欧美人成视频在线 | 国产疯狂伦交大片 | 蜜桃臀无码内射一区二区三区 | 荫蒂添的好舒服视频囗交 | 中文字幕av伊人av无码av | 久久久久se色偷偷亚洲精品av | 午夜丰满少妇性开放视频 | 青草青草久热国产精品 | 少妇愉情理伦片bd | 久久久久久国产精品无码下载 | 好屌草这里只有精品 | 久久国产劲爆∧v内射 | 国产乱码精品一品二品 | 欧美日韩一区二区综合 | 中文字幕久久久久人妻 | 欧美日韩视频无码一区二区三 | 色一情一乱一伦一区二区三欧美 | 麻豆精产国品 | 老太婆性杂交欧美肥老太 | 亚洲一区二区三区含羞草 | 国产精品无码一区二区三区不卡 | 少妇厨房愉情理9仑片视频 | 免费观看的无遮挡av | 永久免费精品精品永久-夜色 | 性色欲网站人妻丰满中文久久不卡 | 亚洲区欧美区综合区自拍区 | 欧美喷潮久久久xxxxx | 性啪啪chinese东北女人 | 最新国产乱人伦偷精品免费网站 | 亚洲日韩乱码中文无码蜜桃臀网站 | 精品人妻av区 | 一区二区传媒有限公司 | 日韩成人一区二区三区在线观看 | 欧美高清在线精品一区 | 精品人妻av区 | 日韩av无码一区二区三区不卡 | 欧美 丝袜 自拍 制服 另类 | 中文久久乱码一区二区 | 国产成人无码av片在线观看不卡 | 少妇性荡欲午夜性开放视频剧场 | 搡女人真爽免费视频大全 | 国产成人无码区免费内射一片色欲 | 国产猛烈高潮尖叫视频免费 | 又色又爽又黄的美女裸体网站 | 色狠狠av一区二区三区 | 中国女人内谢69xxxx | 成人欧美一区二区三区黑人免费 | 久久久婷婷五月亚洲97号色 | 久久无码人妻影院 | 麻豆果冻传媒2021精品传媒一区下载 | 国产成人精品一区二区在线小狼 | 中文字幕 亚洲精品 第1页 | 学生妹亚洲一区二区 | 性欧美疯狂xxxxbbbb | 无码人妻出轨黑人中文字幕 | 欧美 丝袜 自拍 制服 另类 | 午夜免费福利小电影 | 精品日本一区二区三区在线观看 | 成人免费视频在线观看 | 国产综合在线观看 | 又大又黄又粗又爽的免费视频 | 人妻少妇精品无码专区二区 | 欧美日韩一区二区综合 | 国产成人无码一二三区视频 | 精品亚洲成av人在线观看 | 国产精品久久久久9999小说 | 无码人妻丰满熟妇区毛片18 | 免费无码一区二区三区蜜桃大 | 亚洲の无码国产の无码影院 | 国产9 9在线 | 中文 | 俺去俺来也在线www色官网 | 欧美性黑人极品hd | 精品无码成人片一区二区98 | 亚洲毛片av日韩av无码 | 色婷婷av一区二区三区之红樱桃 | 国产精品高潮呻吟av久久 | 国产av人人夜夜澡人人爽麻豆 | 国产超碰人人爽人人做人人添 | 欧美日韩视频无码一区二区三 | 一个人免费观看的www视频 | 欧美日韩一区二区三区自拍 | 狠狠色色综合网站 | 熟妇激情内射com | 国产在热线精品视频 | 欧美黑人性暴力猛交喷水 | 亚洲精品国偷拍自产在线观看蜜桃 | 成熟人妻av无码专区 | www国产亚洲精品久久网站 | 国产亚洲精品久久久久久大师 | 丰满人妻一区二区三区免费视频 | 亚洲精品国偷拍自产在线观看蜜桃 | 亚洲一区二区三区国产精华液 | 无码av中文字幕免费放 | 沈阳熟女露脸对白视频 | 亚洲色大成网站www国产 | 欧美人与动性行为视频 | 精品少妇爆乳无码av无码专区 | 在教室伦流澡到高潮hnp视频 | 人人澡人摸人人添 | 奇米综合四色77777久久 东京无码熟妇人妻av在线网址 | 欧美人与禽猛交狂配 | 色综合久久88色综合天天 | 亚洲日韩中文字幕在线播放 | 国产成人午夜福利在线播放 | 国产精品久久久久久亚洲毛片 | 最新国产乱人伦偷精品免费网站 | 亚洲色无码一区二区三区 | 亚洲国产精品久久久天堂 | 亚洲日韩乱码中文无码蜜桃臀网站 | 兔费看少妇性l交大片免费 | 亚洲娇小与黑人巨大交 | 一本久久a久久精品vr综合 | 亚洲の无码国产の无码影院 | www国产亚洲精品久久网站 | 无遮挡啪啪摇乳动态图 | 日产国产精品亚洲系列 | 97se亚洲精品一区 | 精品国产国产综合精品 | 成人性做爰aaa片免费看 | 欧美老妇交乱视频在线观看 | 国产超碰人人爽人人做人人添 | 鲁一鲁av2019在线 | 国产成人无码av片在线观看不卡 | 亚洲色无码一区二区三区 | 精品国产一区二区三区av 性色 | 亚洲中文字幕av在天堂 | 久久成人a毛片免费观看网站 | 激情爆乳一区二区三区 | 人妻少妇精品无码专区二区 | 无码国产激情在线观看 | 亚洲色成人中文字幕网站 | 露脸叫床粗话东北少妇 | 亚洲人成人无码网www国产 | 97久久超碰中文字幕 | 国产内射老熟女aaaa | 午夜免费福利小电影 | 日日摸夜夜摸狠狠摸婷婷 | 2019午夜福利不卡片在线 | 性生交片免费无码看人 | 东京热男人av天堂 | 国产精品久久久久久亚洲毛片 | 无码人妻出轨黑人中文字幕 | 国产成人无码a区在线观看视频app | 粗大的内捧猛烈进出视频 | 精品久久久无码人妻字幂 | 日本又色又爽又黄的a片18禁 | 中文字幕无码人妻少妇免费 | 成人无码视频在线观看网站 | 欧美日本精品一区二区三区 | 午夜男女很黄的视频 | 亚洲综合无码久久精品综合 | 久激情内射婷内射蜜桃人妖 | 国产国语老龄妇女a片 | 国产做国产爱免费视频 | 国产激情艳情在线看视频 | aa片在线观看视频在线播放 | 丝袜足控一区二区三区 | 国产免费久久精品国产传媒 | 夜精品a片一区二区三区无码白浆 | 极品嫩模高潮叫床 | 老熟妇仑乱视频一区二区 | 久久久久免费看成人影片 | 内射老妇bbwx0c0ck | 九九综合va免费看 | 99re在线播放 | 久久伊人色av天堂九九小黄鸭 | 99久久亚洲精品无码毛片 | 日韩精品一区二区av在线 | 日本熟妇大屁股人妻 | 欧美第一黄网免费网站 | 无码人妻av免费一区二区三区 | 黑人粗大猛烈进出高潮视频 | 一本久道久久综合婷婷五月 | 欧洲美熟女乱又伦 | 精品一区二区不卡无码av | 久久久久久av无码免费看大片 | 国产熟女一区二区三区四区五区 | aa片在线观看视频在线播放 | 精品偷拍一区二区三区在线看 | 强奷人妻日本中文字幕 | 蜜臀av无码人妻精品 | 亚洲精品www久久久 | 99久久无码一区人妻 | 成人无码影片精品久久久 | 亚洲国产精品美女久久久久 | 又湿又紧又大又爽a视频国产 | 美女极度色诱视频国产 | 狠狠色噜噜狠狠狠狠7777米奇 | 国内综合精品午夜久久资源 | 国产真实乱对白精彩久久 | 精品无人国产偷自产在线 | 亚洲s码欧洲m码国产av | 日本丰满熟妇videos | 成人精品视频一区二区 | 欧美成人高清在线播放 | 精品国产av色一区二区深夜久久 | 人人澡人人透人人爽 | 色一情一乱一伦一视频免费看 | 小泽玛莉亚一区二区视频在线 | 中文字幕无码人妻少妇免费 | 欧美国产亚洲日韩在线二区 | 一本久道高清无码视频 | 丰满少妇高潮惨叫视频 | 久久天天躁狠狠躁夜夜免费观看 | 国产偷国产偷精品高清尤物 | 无码av免费一区二区三区试看 | 大色综合色综合网站 | 国精产品一品二品国精品69xx | 理论片87福利理论电影 | 一本色道婷婷久久欧美 | 性欧美牲交xxxxx视频 | 大屁股大乳丰满人妻 | 免费乱码人妻系列无码专区 | 欧美精品一区二区精品久久 | 一个人看的www免费视频在线观看 | 无码人妻精品一区二区三区不卡 | 97夜夜澡人人爽人人喊中国片 | 亚洲一区二区三区四区 | 精品少妇爆乳无码av无码专区 | 伊人久久大香线蕉午夜 | 精品一区二区三区波多野结衣 | 国产性生大片免费观看性 | www成人国产高清内射 | 日本欧美一区二区三区乱码 | 亚洲综合在线一区二区三区 | 国产一区二区三区精品视频 | 少妇被黑人到高潮喷出白浆 | 日本精品人妻无码77777 天堂一区人妻无码 | 动漫av网站免费观看 | 国产av人人夜夜澡人人爽麻豆 | 久久久国产精品无码免费专区 | 九九热爱视频精品 | 一个人看的www免费视频在线观看 | 免费无码一区二区三区蜜桃大 | 国产精品成人av在线观看 | 久久国内精品自在自线 | 亚洲精品一区国产 | 日韩亚洲欧美中文高清在线 | 亚洲熟妇色xxxxx欧美老妇y | 亚洲欧美日韩国产精品一区二区 | 麻花豆传媒剧国产免费mv在线 | 国产成人精品视频ⅴa片软件竹菊 | 在线观看国产午夜福利片 | 国产在线一区二区三区四区五区 | 欧美老熟妇乱xxxxx | 欧美三级a做爰在线观看 | 色狠狠av一区二区三区 | 中文字幕精品av一区二区五区 | 两性色午夜免费视频 | aa片在线观看视频在线播放 | 少妇人妻偷人精品无码视频 | 国产精品办公室沙发 | 5858s亚洲色大成网站www | 精品无人国产偷自产在线 | 久久精品视频在线看15 | 水蜜桃亚洲一二三四在线 | 日本成熟视频免费视频 | 亚洲成色www久久网站 | 国产成人久久精品流白浆 | 狠狠噜狠狠狠狠丁香五月 | 少妇厨房愉情理9仑片视频 | 人妻少妇精品无码专区动漫 | 精品久久综合1区2区3区激情 | 俄罗斯老熟妇色xxxx | 国内精品久久久久久中文字幕 | 少妇的肉体aa片免费 | 噜噜噜亚洲色成人网站 | 爆乳一区二区三区无码 | 欧美一区二区三区 | 久久久国产精品无码免费专区 | 扒开双腿吃奶呻吟做受视频 | 国产欧美精品一区二区三区 | 亚洲中文字幕在线观看 | 久久 国产 尿 小便 嘘嘘 | 中文字幕无码日韩欧毛 | 黑森林福利视频导航 | 综合激情五月综合激情五月激情1 | 欧美日韩视频无码一区二区三 | 久久午夜无码鲁丝片午夜精品 | 色欲综合久久中文字幕网 | 久久综合九色综合97网 | 久久午夜无码鲁丝片午夜精品 | 精品熟女少妇av免费观看 | 蜜臀aⅴ国产精品久久久国产老师 | 欧洲美熟女乱又伦 | 欧美日韩一区二区三区自拍 | 亚洲中文字幕乱码av波多ji | 国产精品无码mv在线观看 | 黄网在线观看免费网站 | 人妻互换免费中文字幕 | 日本一卡二卡不卡视频查询 | 麻豆国产人妻欲求不满 | 激情五月综合色婷婷一区二区 | 红桃av一区二区三区在线无码av | 人妻互换免费中文字幕 | 全黄性性激高免费视频 | 色综合久久久无码网中文 | 亚洲性无码av中文字幕 | 夫妻免费无码v看片 | 午夜精品久久久久久久久 | 日韩欧美群交p片內射中文 | 国产三级精品三级男人的天堂 | 亚洲欧洲无卡二区视頻 | 精品国产青草久久久久福利 | 国产乡下妇女做爰 | 最新版天堂资源中文官网 | 国产又爽又猛又粗的视频a片 | 亚洲欧洲日本无在线码 | 亚洲精品午夜无码电影网 | 日产精品99久久久久久 | 久久久久se色偷偷亚洲精品av | 99riav国产精品视频 | 熟妇人妻激情偷爽文 | 成人无码视频免费播放 | 国产两女互慰高潮视频在线观看 | 国产麻豆精品一区二区三区v视界 | 丰满少妇弄高潮了www | 免费看男女做好爽好硬视频 | 久久久精品国产sm最大网站 | 国产农村妇女高潮大叫 | 国产精品亚洲а∨无码播放麻豆 | 亚洲精品无码国产 | 国产人妻人伦精品 | 精品午夜福利在线观看 | 国产精品a成v人在线播放 | 四虎影视成人永久免费观看视频 | 国产口爆吞精在线视频 | 国产亚洲人成a在线v网站 | 亚洲综合另类小说色区 | 色诱久久久久综合网ywww | 亚洲gv猛男gv无码男同 | 亚洲高清偷拍一区二区三区 | 久久国产自偷自偷免费一区调 | 国产成人无码av在线影院 | 亚洲无人区午夜福利码高清完整版 | 国产日产欧产精品精品app | 亚洲精品成a人在线观看 | 亚洲熟悉妇女xxx妇女av | 77777熟女视频在线观看 а天堂中文在线官网 | 无码国模国产在线观看 | www国产精品内射老师 | 亚洲欧美国产精品久久 | 精品亚洲韩国一区二区三区 | 99er热精品视频 | 欧美国产日产一区二区 | 欧美自拍另类欧美综合图片区 | 中文无码精品a∨在线观看不卡 | 亚洲综合色区中文字幕 | 18无码粉嫩小泬无套在线观看 | 久久婷婷五月综合色国产香蕉 | 亚洲の无码国产の无码步美 | 色一情一乱一伦一区二区三欧美 | 乱人伦人妻中文字幕无码 | 亚洲小说图区综合在线 | 国产精品国产自线拍免费软件 | а天堂中文在线官网 | 中国女人内谢69xxxx |