亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何分析jvm體系結構

發布時間:2022-01-11 15:48:25 來源:億速云 閱讀:107 作者:柒染 欄目:編程語言

今天就跟大家聊聊有關如何分析jvm體系結構,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結了以下內容,希望大家根據這篇文章可以有所收獲。

這不是一篇描述jvm是什么的文章,也不介紹jvm跨平臺的特性,也不是講述jvm安全特性的文章,更不是講解jvm指令操作,數據運算的文章, 下面重點講述類型的生命周期。

類型的生命周期涉及到:類的裝載、jvm體系結構、垃圾回收機制。

為什么要講jvm體系結構?  因為類的裝載和垃圾回收機制都和jvm體系結構息息相關。

那么什么是jvm體系結構呢?

如何分析jvm體系結構

當jvm運行起來的時候,它會向系統申請一片內存區(不同的jvm實現可能不同,有些可以使用虛擬內存),將這塊內存分出一部分存儲許多東西,例如:程序創建的對象,傳遞給方法的參數,返回值,局部變量等等,我們將這塊內存稱之為“運行時數據區”, 運行時數據區可以劃分成方法區、堆、java棧、pc寄存器、本地方法棧。

看到上面這幅圖,和這些解說你可能大概的明白jvm 體系是個啥樣子,但是你或許還不了解運行時數據區里面方法區等用來干嘛的。

  • 方法區:當虛擬機裝載一個class文件的時候,它會從這個class文件包含的二進制數據中解析類型信息。然這些類型信息放到方法區中。因為方法區是被所有線程共享的,所以必須考慮數據的線程安全。假如兩個線程都在試圖找lava的類,在lava類還沒有被加載的情況下,只應該有一個線程去加載,而另一個線程等待。

  • Pc寄存器:每個新線程產生都將得到自己的pc寄存器以及一個java棧幀。

  • 堆:存放程序運行時產生的所有對象。堆是一個線程共享的內存區,所以我們寫多線程程序的時候需要考慮并發。

如何分析jvm體系結構

Java棧:java棧由許多棧幀組成的,如圖,當一個線程調用java方法時,虛擬機壓入一個新的棧幀到java棧中,當方法返回的時候,這個棧幀被從java棧彈出并被拋棄。

那么現在你應該可以想象到一些jvm是怎么工作的了,是不是應該接著講具體工作原理了呢?。但是不急,先了解下類的裝載機制。

了解類的裝載機制之前先了解jvm里面的類裝載器:Bootstrap  Loader、ExtClassLoader 、AppClassLoader;

ExtClassLoader (負責裝載jre下面的rt.jar, charsets.jar)和AppClassLoader(負責轉載classpath下面的類包)是ClassLoader(抽象類)的子類;

Bootstrap Loader(負責裝載jre核心類庫)是根裝載器是c/c++寫的在java里面看不到它。

這三個類裝載器存在父子關系,  根裝載器是 ExtClassLoader父裝載器,ExtClassLoader是AppClassLoader父裝載器;

Jvm中類的裝載也是安全機制沙箱模型的***道門檻。 Java裝載類使用“雙親委派模式”—即全盤負責委托機制。

好現在讓我們了解裝載大概流程; 

當裝載一個類的時候,若是由用戶指定一個類裝載器裝載的話,那么那個類裝載器會先委派給父類裝載器,一直委派到根裝載器,如果裝載的是一個 java.lang.String,由于它是核心類庫的而且已經被裝載過了,那么就會直接返回一個class對象,那么如果是一個根裝載器找不到的類呢?接著就會交給子類(下一級父類)裝載器,如果還是沒有找到類文件,接著就會由之前用戶指定的那個類裝載器裝載。(這里沒有說明裝載超類的過程,請勿疏忽)。

如果是有人惡意的寫了一個基礎類java.lang.String,那么會影響虛擬機嗎? 不會因為這個類最終會交由根裝載器裝載,而根裝載器只會去jre核心類庫加載,最終返回的class類型并不是 用戶寫的String,而且系統自帶的String,也就是說用戶寫String永遠不會被加載。

了解了類裝載器是怎么工作了之后,我們也需要了解下class文件格式;

The ClassFile Structure  ClassFile{  u4 magic;    //魔數  u2 minor_version; //class 次版本號  u2 major_version; //class 主版本號   u2 constant_pool_count;  //常量池計數  cp_info constant_pool[constant_pool_count-1];  //常量池  u2 access_flags;   //修飾符  u2 this_class;  /常量池索引  u2 interfaces_count;    u2 interfaces[interfaces_count];  u2 fields_count;  field_info fields[fields_count];  u2 methods_count;  method_info methods[methods_count];  u2 attributes_count;  attribute_info attributes[attrributes_count];  }

我們需要了解的有很多,但是我們難以理解的就是 cp_info constant_pool 常量池;

一個常量池里面有很多表

CONSTANT_Utf8 UTF-8編碼的Unicode字符串  CONSTANT_Integer   int類型的字面值  CONSTANT_Float float類型的字面值  CONSTANT_Long          long類型的字面值  CONSTANT_Double double類型的字面值  CONSTANT_Class 對一個類或接口的符號引用  CONSTANT_String String類型字面值的引用  CONSTANT_Fieldref 對一個字段的符號引用  CONSTANT_Methodref   對一個類中方法的符號引用  CONSTANT_InterfaceMethodref 對一個接口中方法的符號引用  CONSTANT_NameAndType   對一個字段或方法的部分符號引用

這些表結構我也不解釋了,如果對class文件不夠了解也沒什么關系,知道個大概也行。那么我們了解了 jvm體系,類裝載器工作流程,那么我們細看下 類裝載器工作中 ,jvm運行時數據區的變化,方法區里面的結構等等。

在類裝載的過程中, 每一個類裝載器都會在方法區里面形成一張表,這張表記載著該裝載器和對應的類的權限定名。沒這么一張表就形成了jvm內部的命名空間。同時在方法區里面還該類的常量池等信息。

那么說到這些,其實這個過程還是很模糊,而且很多知識也落下了,那么我們現在看一個詳細一點的裝載過程。

當裝載一個普通的類的時候,即調用類裝載器的loadClass方法, 如果希望裝載的類還沒有被裝載到命名空間,那么jvm會傳遞一個該類型的全限定名給類裝載器,也就是常量池CONSTANT_Class_info(該表存儲著父類、類裝載器等信息)入口的裝載器,來試圖裝載被引用的類型,如果發起引用的類型是被jvm裝載器定義的,那么由jvm類裝載器裝載,否則由用戶自定義裝載器裝載,那么一旦被引用的類型被裝載了,jvm仔細檢查它的二進制數據,如果類是是一個類,并且不是java.lang.Object。 jvm根據數據得到它的全限定名進行裝載(遞歸的應用了)這個過程還需要遞歸超接口。

裝載差不多講完了,一個完整的過程 是: 裝載—連接---初始化

那么連接和初始化就一帶而過了, 重點放在垃圾回收。

連接的過程主要是驗證(確認類型符合java語言的語義,并且它不會危及虛擬機的完整性)、準備(java 虛擬機為類變量分配內存,設計默認初始值)、解析(在類型的常量池中尋找類、接口、字段和方法的符合引用,把這些符號引用替換成直接引用的過程)。

初始化的時候,如果類存在直接超類,且超類還沒有被初始化,就先初始化直接超類。初始化接口并不需要初始化它的父接口。

補充:

Jvm當運行某個方法的時候,先把這個方法壓入java棧中,里面包含局部變量等信息,那么對象放入哪里呢? 壓入棧的是對象的引用, 即變量, 所有的對象都存儲在堆中。

為什么要把對象放入堆,把變量之類的數據放入棧呢? 說白了,對象太大了,存入棧中運算麻煩。(當然標準的回答不是這樣的,我這里僅僅是說明實質)

了解了這么一個過程之后,我們必然要了解垃圾回收機制了。

基本回收算法

1. 引用計數:比較古老的回收算法。原理是此對象有一個引用,即增加一個計數,刪除一個引用則減少一個計數。垃圾回收時,只用收集計數為0的對象。此算法最致命的是無法處理循環引用的問題。

2. 標記-清除:此算法執行分兩階段。第一階段從引用根節點開始標記所有被引用的對象,第二階段遍歷整個堆,把未標記的對象清除。此算法需要暫停整個應用,同時,會產生內存碎片。

3. 復制:此算法把內存空間劃為兩個相等的區域,每次只使用其中一個區域。垃圾回收時,遍歷當前使用區域,把正在使用中的對象復制到另外一個區域中。次算法每次只處理正在使用中的對象,因此復制成本比較小,同時復制過去以后還能進行相應的內存整理,不過出現“碎片”問題。當然,此算法的缺點也是很明顯的,就是需要兩倍內存空間。

4. 標記-整理:此算法結合了“標記-清除”和“復制”兩個算法的優點。也是分兩階段,最后階段從根節點開始標記所有被引用對象,第二階段遍歷整個堆,把清除未標記對象并且把存活對象“壓縮”到堆的其中一塊,按順序排放。此算法避免了“標記-清除”的碎片問題,同時也避免了“復制”算法的空間問題。

5. 增量收集:實施垃圾回收算法,即:在應用進行的同時進行垃圾回收。

6. 分代:基于對對象生命周期分析后得出的垃圾回收算法。把對象分為年青代、年老代、持久代,對不同生命周期的對象使用不同的算法(上述方式中的一個)進行回收。

看完上述內容,你們對如何分析jvm體系結構有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注億速云行業資訊頻道,感謝大家的支持。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

jvm
AI

博爱县| 九寨沟县| 南陵县| 南召县| 绥滨县| 巴林左旗| 景宁| 定陶县| 石楼县| 吴旗县| 平昌县| 昭苏县| 政和县| 日喀则市| 左云县| 新泰市| 潞西市| 广德县| 象州县| 开远市| 博乐市| 灵寿县| 冀州市| 凤城市| 宣城市| 怀柔区| 洛隆县| 富宁县| 菏泽市| 扶余县| 江油市| 石台县| 丰原市| 天峨县| 奉新县| 沙雅县| 大新县| 军事| 磐安县| 阿克苏市| 桃源县|