日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

深入理解jvm虚拟机一

發布時間:2023/12/10 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 深入理解jvm虚拟机一 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

深入理解jvm虛擬機一

  • JVM
    • Jvm基本概念
    • 運行過程
    • 內存區域
      • 程序計數器
      • 虛擬機棧
      • 本地方法棧
      • 方法區/永久代
      • 1.8元數據區
  • 回收與收集
    • 兩大回收
      • 引用計數法
      • 可達性分析
    • 四大引用
      • 強引用
      • 軟引用
      • 弱引用
      • 虛引用
  • 回收算法
    • 標記-清除(Mark-Sweep)
    • 復制(Copying)
    • 標記-整理(Mark-Compact)
    • 分代算法
      • 新生代
      • 老年代

JVM

Java與Jvm的關系似魚和水,而開發者與Jvm的關系似情侶相愛相殺。愛它不用像C、C++擺弄指針,把內存控制的權利交給它,恨它一旦出現內存泄漏和溢出方面的問題,如果不理解它的話,無從下手,更別談優化了。

Jvm基本概念

JVM及Java虛擬機,是可運行Java代碼的假象計算機,Jvm是運行在操作系統之上的,它與硬件沒有直接交互。

運行過程

我們都知道Java源文件,通過編譯器,能夠生成相應的.class文件,也就是字節碼文件,而字節碼文件又能通過jvm的解釋器,編譯成機器上的機器碼,大概流程如下:Java源文件—>編譯器—>字節碼文件—>jvm—>機器碼,雖然每個平臺的解釋器不同,但是虛擬機是相同的,這也就是為什么java是跨平臺的。

內存區域

Jvm把Java程序運行時的內存劃分為不同的數據區域,如圖所示:

jvm內存區域主要分為線程私有(程序計數器、虛擬機棧、本地方法棧)、線程共享(堆、方法區)、直接內存,線程私有的生命周期與線程相同,依賴用戶線程的啟動/結束而創建/銷毀,線程共享隨虛擬機開啟/關閉而創建/銷毀。直接內存并不是jvm運行時數據區的一部分,在 JDK 1.4 引入的 NIO 提供了基于 Channel 與 Buffer 的 IO 方式, 它可以使用 Native 函數庫直接分配堆外內存,然后使用DirectByteBuffer 對象作為這塊內存的引用進行操作,這樣就避免了在 Java堆和 Native 堆中來回復制數據,因此在一些場景中可以顯著提高性能。

程序計數器

一塊較小的內存空間,是當前線程所執行到的字節碼的行號指令器,每個線程都是獨立運行的,如果正在執行的是Java方法,則記錄的是正在執行的虛擬機字節碼行號,如果是native方法,則為空,此區域也是唯一一個在虛擬機中沒有規定任何 OOM 情況的區域。

虛擬機棧

生命周期與線程相同,是描述Java方法執行的內存模型,每個方法在執行的時候都會創建一個棧針,用于存放局部變量表、操作數棧、動態鏈接、方法出口等信息。每一個方法從調用直至執行結束對應棧針在虛擬機中的入棧和出棧。如果虛擬機棧請求棧深度大于虛擬機所允許的深度,將拋出StrakOverflowError異常;如果擴展時無法申請到足夠的內存,將拋出OOM異常,可以通過xss參數來調節大小,默認1M。

本地方法棧

與虛擬機中作用相似,區別是虛擬機棧為Java方法服務的,而本地方法棧是為native服務的,它也會拋出同虛擬機棧一樣的異常。

是用來存放被創建的對象、數組,也是垃圾回收器進行垃圾回收的主要內存區域,可以通過xms、xmx來設置初始化堆大小、最大堆大小,默認是最小1/64,最大1/4。由于現代的垃圾回收器都是采用分代回收,因此堆從GC的角度還可以細分為:新生代(Eden區、From Survivor區、To Survivor區)和老年代。

方法區/永久代

用來存放被Jvm加載的類信息、常量、靜態變量、即時編譯器編譯后的代碼數據,HotSpot VM把GC分代收集擴展至方法區, 即使用Java堆的永久代來實現方法區, 這樣 HotSpot 的垃圾收集器就可以像管理 Java 堆一樣管理這部分內存,而不必為方法區開發專門的內存管理器(永久帶的內存回收的主要目標是針對常量池的回收和類型的卸載,因此收益一般很小),通過設置PermSize和MaxPermSize設置初始化和最大上限(1.7以前)

1.8元數據區

在Jdk1.8取消了永久代,不在使用虛擬機內的永久代而是改用本地內存——元數據區(Metaspace),通過MetaspaceSize和MaxMetaspaceSize來設置初始化和最大上限。至于為什么不使用,理由如下:
1. 永久代調優很難,會為 GC 帶來不必要的復雜度,并且回收效率偏低。
2. 字符串存在永久代中,容易出現性能問題和內存溢出。
3. 類及方法的信息等比較難確定其大小,因此對于永久代的大小指定比較困難,太小容易出現永久代溢出,太大則容易導致老年代溢出。
4. Oracle 可能會將HotSpot 與 JRockit 合二為一。

回收與收集

兩大回收

在堆里幾乎存放了所有的實例,垃圾回收前,需要判斷哪些對象“活著”,哪些對象“死去”。

引用計數法

在java中引用和對象是有關聯的,如果操作對象就必須用引用來進行。因此通過引用計數法來判斷一個對象是否可以被回收,被引用則計數器+1,引用失效則計數器-1,直到引用計數為0,這是基本的也是比較高效的,但是無法避免相互引用。

可達性分析

為了避免相互引用問題,Java使用的可達性分析的方法,通過“GC roots”對象作為起點搜索,如果沒有可達路徑,則該對象不可達,可以被回收。即使這樣,也不是說必須回收,如果該對象覆蓋了finalize()方法,重新引用對象可以進行自救,只會自救一次。因為這個方法對運行代價高,不穩定性,因此也不推薦使用。在Java中GC roots對象包括下面四種:
1. 虛擬機棧(棧針中變量表)引用的對象
2. 本地方法棧(JNI)引用的對象
3. 方法區中類靜態屬性引用的對象
4. 方法區中常量引用的對象

四大引用

無論是引用計數法還是可達性分析,都與Java中引用有關。

強引用

Java中常見的引用,Object obj=new Object,即使虛擬機拋出OOM(內存溢出)也不會釋放這部分引用,這部分容易造成內存泄漏。

軟引用

需要用SoftReference類實現,描述一些還有用但非必需的對象,當系統內存足夠時,是不會回收這部分資源,只有在系統內存不夠時,這部分則會被回收。

弱引用

需要用WeakReference類實現,它比軟引用存活時間更短,它的生命周期只存活在下一次垃圾回收之前。

虛引用

需要 PhantomReference 類來實現,隨時被回收,它不能單獨使用,必須和引用隊列聯合使用,虛引用的主要作用是跟蹤對象被垃圾回收的狀態。

回收算法

標記-清除(Mark-Sweep)

最基本的垃圾回收算法,分為兩個階段:標記、清除。標記可以被回收的對象,清除所有被標記的對象。
缺點:空間碎片化嚴重,標記清除,效率都不高。

復制(Copying)

為了解決碎片化問題,按內存容量一分為二,每次只用其中的一塊,當一塊存滿時候,把存活的對象復制到另外一塊上,把已使用的內存塊清除。
缺點:內存使用率低。

標記-整理(Mark-Compact)

結合以上兩個算法,標記類似于Mark-Sweep,標記后不是清理對象,而是把存活的對象移向內存的一端,把端以外的對象清除。

分代算法

分代算法是目前大多數JVM使用的回收算法,根據對象存活的不同生命周期來劃分內存區域,一般化為老年代和新生代,老年代特點每次垃圾回收只有少量對象被回收,新生代特點每次垃圾回收都會有大量對象被回收,這樣就可以根據不同區域來選擇不同的回收算法。

新生代

目前大多數JVM新生代都是采用復制算法,因為新生代需要回收大部分對象,并不是按照1:1來劃分新生代,而是劃分為一塊較大的Eden空間和兩個較小的Survivor空間(from ,to),每次都使用Eden和一部分Survivor區域,當進行回收時,把存活的對象復制到另一塊Survivor空間,通過xmn調整新生代大小。

對象優先分配在新生代,大對象直接則進入老年代(設置-xx:PretenureSizeThreshold參數),長期存活的對象進入老年代(設置-xx:MaxTenuringThreshold,默認15次),為了更加適應程序的內存狀態,并不是要求年齡必須到15才會進入老年代,如果在Survivor空間中所有對象大小的總和大于Survivor空間的一半,年齡大于或等于該年齡的對象也可以直接進入老年代。

老年代

老年代存放生命周期比較長的,對象相對穩定,所以采用標記清除或者整理。
Minor GC:當新生代內存不足,回收新生代(Ende區和兩個Survivor)內存。
Major GC:清理老年代,一般伴隨著一次Minor,效率比Minor要慢。
Full GC:清理整個堆空間,一般調優也就是堆fullGC進行優化,因為它會停止操作,單一線程進行GC。

總結

以上是生活随笔為你收集整理的深入理解jvm虚拟机一的全部內容,希望文章能夠幫你解決所遇到的問題。

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