国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

一文了解JVM

whatsns / 681人閱讀

摘要:而使用虛擬機是實現(xiàn)這一特點的關鍵。每個字節(jié)碼指令都由一個字節(jié)的操作碼和附加的操作數(shù)組成。字節(jié)碼可以通過以下兩種方式轉換成合適的語言解釋器一條一條地讀取,解釋并執(zhí)行字節(jié)碼執(zhí)行,所以它可以很快地解釋字節(jié)碼,但是執(zhí)行起來會比較慢。

一、什么是JVM

JVM是Java Virtual Machine(Java 虛擬機)的縮寫,JVM是一種用于計算設備的規(guī)范,它是一個虛構出來的計算機,是通過在實際的計算機上仿真模擬各種計算機功能來實現(xiàn)的。

Java語言的一個非常重要的特點就是平臺無關性。而使用Java虛擬機是實現(xiàn)這一特點的關鍵。一般的高級語言如果要在不同的平臺上運行,至少需要編譯成不同的目標代碼。而引入Java語言虛擬機后,Java語言在不同平臺上運行時不需要重新編譯。Java語言使用Java虛擬機屏蔽了與具體平臺相關的信息,使得Java語言編譯程序只需生成在Java虛擬機上運行的目標代碼(字節(jié)碼),就可以在多種平臺上不加修改地運行。Java虛擬機在執(zhí)行字節(jié)碼時,把字節(jié)碼解釋成具體平臺上的機器指令執(zhí)行。這就是Java的能夠“一次編譯,到處運行”的原因。

二、JVM總體概述

JVM總體上是由類裝載子系統(tǒng)(ClassLoader)、運行時數(shù)據區(qū)、執(zhí)行引擎、垃圾收集這四個部分組成。其中我們最為關注的運行時數(shù)據區(qū),也就是JVM的內存部分則是由方法區(qū)(Method Area)、JAVA堆(Java Heap)、虛擬機棧(JVM Stack)、程序計數(shù)器、本地方法棧(Native Method Stack)這幾部分組成。

三、JVM體系結構

3.1 類裝載子系統(tǒng)

Class Loader類加載器負責加載.class文件,class文件在文件開頭有特定的文件標示,并且ClassLoader負責class文件的加載等,至于它是否可以運行,則由Execution Engine決定。

3.2 運行時數(shù)據區(qū)

棧管運行,堆管存儲。JVM調優(yōu)主要是優(yōu)化Java堆和方法區(qū)。

3.2.1 方法區(qū)(Method Area)

方法區(qū)是各線程共享的內存區(qū)域,它用于存儲已被JVM加載的類信息、常量、靜態(tài)變量、運行時常量池等數(shù)據。

3.2.2 Java堆(Java Heap)

Java堆是各線程共享的內存區(qū)域,在JVM啟動時創(chuàng)建,這塊區(qū)域是JVM中最大的, 用于存儲應用的對象和數(shù)組,也是GC主要的回收區(qū),一個 JVM 實例只存在一個堆內存,堆內存的大小是可以調節(jié)的。類加載器讀取了類文件后,需要把類、方法、常變量放到堆內存中,以方便執(zhí)行器執(zhí)行,堆內存分為三部分:新生代、老年代、永久代。

說明:

Jdk1.6及之前:常量池分配在永久代 。

Jdk1.7:有,但已經逐步“去永久代” 。

Jdk1.8及之后:無永久代,改用元空間代替(java.lang.OutOfMemoryError: PermGen space,這種錯誤將不會出現(xiàn)在JDK1.8中)。

3.2.3 Java棧(JVM Stack)

1) 棧是什么

Java棧是線程私有的,是在線程創(chuàng)建時創(chuàng)建,它的生命期是跟隨線程的生命期,線程結束棧內存也就釋放,對于棧來說不存在垃圾回收問題,只要線程一結束該棧就Over,生命周期和線程一致。基本類型的變量和對象的引用變量都是在函數(shù)的棧內存中分配。

2) 棧存儲什么

每個方法執(zhí)行的時候都會創(chuàng)建一個棧幀,棧幀中主要存儲3類數(shù)據:

局部變量表:輸入參數(shù)和輸出參數(shù)以及方法內的變量;

棧操作:記錄出棧和入棧的操作;

棧幀數(shù)據:包括類文件、方法等等。

3) 棧運行原理

棧中的數(shù)據都是以棧幀的格式存在,棧幀是一個內存區(qū)塊,是一個數(shù)據集,是一個有關方法和運行期數(shù)據的數(shù)據集。每一個方法被調用直至執(zhí)行完成的過程,就對應著一個棧幀在棧中從入棧到出棧的過程。

4) 本地方法棧(Native Method Stack)

本地方法棧和JVM棧發(fā)揮的作用非常相似,也是線程私有的,區(qū)別是JVM棧為JVM執(zhí)行Java方法(也就是字節(jié)碼)服務,而本地方法棧為JVM使用到的Native方法服務。它的具體做法是在本地方法棧中登記native方法,在執(zhí)行引擎執(zhí)行時加載Native Liberies.有的虛擬機(比如Sun Hotpot)直接把兩者合二為一。

5) 程序計數(shù)器(Program Counter Register)

程序計數(shù)器是一塊非常小的內存空間,幾乎可以忽略不計,每個線程都有一個程序計算器,是線程私有的,可以看作是當前線程所執(zhí)行的字節(jié)碼的行號指示器,指向方法區(qū)中的方法字節(jié)碼(下一個將要執(zhí)行的指令代碼),由執(zhí)行引擎讀取下一條指令。

6) 運行時常量池

運行時常量池是方法區(qū)的一部分,用于存放編譯器生成的各種字面量和符號引用,這部分內容將在類加載后存放到方法區(qū)的運行時常量池中。相較于Class文件常量池,運行時常量池更具動態(tài)性,在運行期間也可以將新的變量放入常量池中,而不是一定要在編譯時確定的常量才能放入。最主要的運用便是String類的intern()方法。

3.3 執(zhí)行引擎(Execution Engine)

執(zhí)行引擎執(zhí)行包在裝載類的方法中的指令,也就是方法。執(zhí)行引擎以指令為單位讀取Java字節(jié)碼。它就像一個CPU一樣,一條一條地執(zhí)行機器指令。每個字節(jié)碼指令都由一個1字節(jié)的操作碼和附加的操作數(shù)組成。執(zhí)行引擎取得一個操作碼,然后根據操作數(shù)來執(zhí)行任務,完成后就繼續(xù)執(zhí)行下一條操作碼。

不過Java字節(jié)碼是用一種人類可以讀懂的語言編寫的,而不是用機器可以直接執(zhí)行的語言。因此,執(zhí)行引擎必須把字節(jié)碼轉換成可以直接被JVM執(zhí)行的語言。字節(jié)碼可以通過以下兩種方式轉換成合適的語言:

解釋器: 一條一條地讀取,解釋并執(zhí)行字節(jié)碼執(zhí)行,所以它可以很快地解釋字節(jié)碼,但是執(zhí)行起來會比較慢。這是解釋執(zhí)行語言的一個缺點。

即時編譯器:用來彌補解釋器的缺點,執(zhí)行引擎首先按照解釋執(zhí)行的方式來執(zhí)行,然后在合適的時候,即時編譯器把整段字節(jié)碼編譯成本地代碼。然后,執(zhí)行引擎就沒有必要再去解釋執(zhí)行方法了,它可以直接通過本地代碼去執(zhí)行。執(zhí)行本地代碼比一條一條進行解釋執(zhí)行的速度快很多,編譯后的代碼可以執(zhí)行的很快,因為本地代碼是保存在緩存里的。

3.4 垃圾收集(Garbage Collection, GC) 3.4.1 什么是垃圾收集

垃圾收集即垃圾回收,簡單的說垃圾回收就是回收內存中不再使用的對象。所謂使用中的對象(已引用對象),指的是程序中有指針指向的對象;而未使用中的對象(未引用對象),則沒有被任何指針給指向,因此占用的內存也可以被回收掉。

垃圾回收的基本步驟分兩步:

查找內存中不再使用的對象(GC判斷策略)

釋放這些對象占用的內存(GC收集算法)

3.4.2 GC判斷策略

1) 引用計數(shù)算法

引用計數(shù)算法是給對象添加一個引用計數(shù)器,每當有一個引用它時,計數(shù)器值就加1;當引用失效時,計數(shù)器值就減1;任何時刻計數(shù)器都為0的對象就是不可能再被使用的對象。缺點:很難解決對象之間相互循環(huán)引用的問題。

2) 根搜索算法

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

在Java語言里,可作為GC Roots的對象包括以下幾種:

虛擬機棧(棧幀中的本地變量表)中引用的對象;

方法區(qū)中類靜態(tài)屬性引用的對象;

方法區(qū)中常量應用的對象;

本地方法棧中JNI(Native方法)引用的對象。

注:在根搜索算法中不可達的對象,也并非是“非死不可”的,因為要真正宣告一個對象死亡,至少要經歷兩次標記過程:第一次是標記沒有與GC Roots相連接的引用鏈;第二次是GC對在F-Queue執(zhí)行隊列中的對象進行的小規(guī)模標記(對象需要覆蓋finalize()方法且沒被調用過)。

3.4.3 GC收集算法

1) 標記-清除算法(Mark-Sweep)

標記-清楚算法采用從根集合(GC Roots)進行掃描,首先標記出所有需要回收的對象(根搜索算法),標記完成后統(tǒng)一回收掉所有被標記的對象。

該算法有兩個問題:

效率問題:標記和清除過程的效率都不高;

空間問題:標記清除后會產生大量不連續(xù)的內存碎片, 空間碎片太多可能會導致在運行過程中需要分配較大對象時無法找到足夠的連續(xù)內存而不得不提前觸發(fā)另一次垃圾收集。

2) 復制算法(Copying)

復制算法是將可用內存按容量劃分為大小相等的兩塊, 每次只用其中一塊, 當這一塊的內存用完, 就將還存活的對象復制到另外一塊上面, 然后把已使用過的內存空間一次清理掉。

3) 標記-整理算法(Mark-Compact)

標記整理算法的標記過程與標記清除算法相同, 但后續(xù)步驟不再對可回收對象直接清理, 而是讓所有存活的對象都向一端移動,然后清理掉端邊界以外的內存。

4) 分代收集算法(Generational Collection)

分代收集算法是目前大部分JVM的垃圾收集器采用的算法。它的核心思想是根據對象存活的生命周期將內存劃分為若干個不同的區(qū)域。一般情況下將堆區(qū)劃分為老年代(Tenured Generation)和新生代(Young Generation),在堆區(qū)之外還有一個代就是永久代(Permanet Generation)。老年代的特點是每次垃圾收集時只有少量對象需要被回收,而新生代的特點是每次垃圾回收時都有大量的對象需要被回收,那么就可以根據不同代的特點采取最適合的收集算法。

新生代(Young Generation)的回收算法(以復制算法為主)

所有新生成的對象首先都是放在年輕代的。年輕代的目標就是盡可能快速的收集掉那些生命周期短的對象。

新生代內存按照8:1:1的比例分為一個eden區(qū)和兩個survivor(survivor0,survivor1)區(qū)。一個Eden區(qū),兩個 Survivor區(qū)(一般而言)。大部分對象在Eden區(qū)中生成。回收時先將eden區(qū)存活對象復制到一個survivor0區(qū),然后清空eden區(qū),當這個survivor0區(qū)也存放滿了時,則將eden區(qū)和survivor0區(qū)存活對象復制到另一個survivor1區(qū),然后清空eden和這個survivor0區(qū),此時survivor0區(qū)是空的,然后將survivor0區(qū)和survivor1區(qū)交換,即保持survivor1區(qū)為空, 如此往復。

當survivor1區(qū)不足以存放 eden和survivor0的存活對象時,就將存活對象直接存放到老年代。若是老年代也滿了就會觸發(fā)一次Full GC(Major GC),也就是新生代、老年代都進行回收。

新生代發(fā)生的GC也叫做Minor GC,MinorGC發(fā)生頻率比較高(不一定等Eden區(qū)滿了才觸發(fā))。

老年代(Tenured Generation)的回收算法(以標記-清除、標記-整理為主)

在年輕代中經歷了N次垃圾回收后仍然存活的對象,就會被放到老年代中。因此,可以認為老年代中存放的都是一些生命周期較長的對象。

內存比新生代也大很多(大概比例是1:2),當老年代內存滿時觸發(fā)Major GC即Full GC,F(xiàn)ull GC發(fā)生頻率比較低,老年代對象存活時間比較長,存活率標記高。

永久代(Permanet Generation)的回收算法

用于存放靜態(tài)文件,如Java類、方法等。永久代對垃圾回收沒有顯著影響,但是有些應用可能動態(tài)生成或者調用一些class,例如Hibernate 等,在這種時候需要設置一個比較大的永久代空間來存放這些運行過程中新增的類。永久代也稱方法區(qū)。方法區(qū)主要回收的內容有:廢棄常量和無用的類。對于廢棄常量也可通過根搜索算法來判斷,但是對于無用的類則需要同時滿足下面3個條件:

該類所有的實例都已經被回收,也就是Java堆中不存在該類的任何實例;

加載該類的ClassLoader已經被回收;

該類對應的java.lang.Class對象沒有在任何地方被引用,無法在任何地方通過反射訪問該類的方法。

3.4.4 垃圾收集器

1) Serial收集器(復制算法)

新生代單線程收集器,標記和清理都是單線程,優(yōu)點是簡單高效。是client級別默認的GC方式,可以通過-XX:+UseSerialGC來強制指定。

2) Serial Old收集器(標記-整理算法)

老年代單線程收集器,Serial收集器的老年代版本。

3) ParNew收集器(停止-復制算法)

新生代多線程收集器,其實就是Serial收集器的多線程版本,在多核CPU環(huán)境下有著比Serial更好的表現(xiàn)。

4) Parallel Scavenge收集器(停止-復制算法)

新生代并行的多線程收集器,追求高吞吐量,高效利用CPU。吞吐量一般為99%, 吞吐量= 用戶線程時間/(用戶線程時間+GC線程時間)。適合后臺應用等對交互相應要求不高的場景。是server級別默認采用的GC方式,可用-XX:+UseParallelGC來強制指定,用-XX:ParallelGCThreads=4來指定線程數(shù)。

5) Parallel Old收集器(停止-復制算法)

老年代并行的多線程收集器,Parallel Scavenge收集器的老年代版本,并行收集器,吞吐量優(yōu)先。

6) CMS(Concurrent Mark Sweep)收集器(標記-清除算法)

CMS收集器是一種以獲取最短回收停頓時間為目標的收集器,CMS收集器是基于“標記--清除”(Mark-Sweep)算法實現(xiàn)的,整個過程分為四個步驟:

初始標記: 標記GC Roots能直接關聯(lián)到的對象,速度很快;

并發(fā)標記: 進行GC Roots Tracing的過程;

重新標記: 修正并發(fā)標記期間因用戶程序繼續(xù)運作而導致標記產生變動的那一部分對象的標記記錄,這個階段的停頓時間一般會比初始標記階段稍長一些,但比并發(fā)標記時間短;

并發(fā)清除: 整個過程中耗時最長的并發(fā)標記和并發(fā)清除過程收集器線程都可以與用戶線程一起工作,所以,從總體上來說,CMS收集器的內存回收過程是與用戶線程一起并發(fā)執(zhí)行的。

優(yōu)點:并發(fā)收集、低停頓

缺點:對CPU資源非常敏感、無法處理浮動垃圾、產生大量空間碎片。

7) G1(Garbage First)收集器(標記-整理算法)

G1是一款面向服務端應用的垃圾收集器,是基于“標記-整理”算法實現(xiàn)的,與其他GC收集器相比,G1具備如下特點:

并行與并發(fā)

分代收集

空間整合

可預測性的停頓

G1運作步驟:

初始標記(stop the world事件,CPU停頓只處理垃圾)

并發(fā)標記(與用戶線程并發(fā)執(zhí)行)

最終標記(stop the world事件,CPU停頓處理垃圾)

篩選回收(stop the world事件,根據用戶期望的GC停頓時間回收)

3.4.5 垃圾收集結構圖

作者:郭曉利

來源:宜信技術學院

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/75547.html

相關文章

  • Java相關

    摘要:本文是作者自己對中線程的狀態(tài)線程間協(xié)作相關使用的理解與總結,不對之處,望指出,共勉。當中的的數(shù)目而不是已占用的位置數(shù)大于集合番一文通版集合番一文通版垃圾回收機制講得很透徹,深入淺出。 一小時搞明白自定義注解 Annotation(注解)就是 Java 提供了一種元程序中的元素關聯(lián)任何信息和著任何元數(shù)據(metadata)的途徑和方法。Annotion(注解) 是一個接口,程序可以通過...

    wangtdgoodluck 評論0 收藏0
  • 一文了解JVM全部垃圾回收器,從Serial到ZGC

    摘要:是目前的實驗收集器。也是需要暫停程序一切的工作,然后多線程執(zhí)行垃圾回收。與最大的不同,它關注的是垃圾回收的吞吐量。這里的吞吐量指的是總時間與垃圾回收時間的比例。篩選回收,評估標記垃圾,根據模式回收垃圾。 《對象搜索算法與回收算法》介紹了垃圾回收的基礎算法,相當于垃圾回收的方法論。接下來就詳細看看垃圾回收的具體實現(xiàn)。 上文提到過現(xiàn)代的商用虛擬機的都是采用分代收集的,不同的區(qū)域用不同的收集...

    jasperyang 評論0 收藏0
  • 必知必會JVM垃圾回收——對象搜索算法與回收算法

    垃圾回收(GC)是JVM的一大殺器,它使程序員可以更高效地專注于程序的開發(fā)設計,而不用過多地考慮對象的創(chuàng)建銷毀等操作。但是這并不是說程序員不需要了解GC。GC只是Java編程中一項自動化工具,任何一個工具都有它適用的范圍,當超出它的范圍的時候,可能它將不是那么自動,而是需要人工去了解與適應地適用。 擁有一定工作年限的程序員,在工作期間肯定會經常碰到像內存溢出、內存泄露、高并發(fā)的場景。這時候在應對這...

    LuDongWei 評論0 收藏0
  • 一起學并發(fā)編程 - 鉤子函數(shù)(shutdownHook)

    摘要:在退出時執(zhí)行必要的挽救措施。在這種情況下,一旦被提供,等待一個進程終止指定的時間。如果進程在該時間限制內沒有終止,則通過發(fā)出或中的對等方強制終止進程。所以有可能這是在中途執(zhí)行時發(fā)生的。 shutdownHook是一種特殊的結構,它允許開發(fā)人員插入JVM關閉時執(zhí)行的一段代碼。這種情況在我們需要做特殊清理操作的情況下很有用 用途 在Jboss,Jetty等容器中都可以看到shutdown...

    qpal 評論0 收藏0
  • JVM(2)--一文讀懂垃圾回收

    摘要:對象存不進去,會又一次觸發(fā)垃圾回收。也就是說,它在進行垃圾回收時,必須暫停其他所有線程。我們來看一個名詞吞吐量。吞吐量運行用戶代碼時間運行用戶代碼時間垃圾收集時間。也就是說,收集器會嚴格控制吞吐量,至于這個吞吐量是多少,這個可以人為設置。 與其他語言相比,例如c/c++,我們都知道,java虛擬機對于程序中產生的垃圾,虛擬機是會自動幫我們進行清除管理的,而像c/c++這些語言平臺則需要...

    MRZYD 評論0 收藏0

發(fā)表評論

0條評論

whatsns

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<