中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

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

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

網狐榮耀棋牌最新版源碼:含PC全套源碼+部分手機端lua源碼(含10多個子游戲)

發布時間:2020-08-19 08:45:06 來源:ITPUB博客 閱讀:1725 作者:sadasd2323 欄目:大數據
 網狐榮耀棋牌最新版源碼:http://hubawl.com/thread-164-1-1.html
含PC全套源碼+部分手機端lua源碼(含10多個子游戲)

網狐榮耀棋牌最新版源碼:含PC全套源碼+部分手機端lua源碼(含10多個子游戲)

運行時數據區
  •     線程共享的數據區:方法區、堆、本地庫接口
  •     線程隔離的數據區:虛擬機棧、本地方法棧、程序計數器

程序計數器:是一塊較小的內存空間,它可以看做是當前線程所執行的字節碼的行號指示器。此內存區域是唯一一個在Java虛擬機規范中沒有規定任何OutOfMemoryError情況的區域。

Java虛擬機棧:它的生命周期與線程相同。
  •     虛擬機棧描述的是Java方法執行的內存模型:每個方法在執行的同時都會創建一個棧幀用于存儲局部變量表、操作數棧、動態鏈接、方法出口等信息。每一個方法從調用直至執行完成的過程,就對應著一個棧幀在虛擬機棧中入棧到出棧的過程。
  •     局部變量表存放了編譯期可知的各種基本數據類型、對象引用reference類型,它不等同于對象本身)和returnAddress類型(指向了一條字節碼指令的地址)。其中64位長度的longdouble類型的數據會占用2個局部變量空間,其余的數據類型只占用1個。局部變量表所需的內存空間在編譯期間完成分配,當進入一個方法時,這個方法需要幀中分配多大的局部變量空間是完全確定的,在方法運行期間不會改變局部變量表的大小。
  •     在Java虛擬機規范中,對這個區域規定了兩種異常狀況:如果線程請求的棧深度大于虛擬機所允許的深度,將拋出StackOverflowError異常;如果虛擬機棧可以動態擴展,如果擴展時無法申請到足夠的內存,就會拋出OutOfMemoryError異常。

本地方法棧:本地方法棧與虛擬機棧所發揮的作用是非常相似的,它們之間的區別不過是虛擬機棧為虛擬機執行java方法(也就是字節碼)服務,而本地方法棧則為虛擬機使用到的Native方法服務。在虛擬機規范中對本地方法棧中方法使用的語言、使用方式與數據結構并沒有強制規定,因此具體的虛擬機可以自由實現它。有的虛擬機(如Sun HotSpot 虛擬機)直接就把本地方法棧和虛擬機棧合二為一。與虛擬機棧一樣,本地方法棧也會拋出StackOverflowError  OutOfMemoryError 異常。

Java堆:對于大多數應用來說,Java堆是Java虛擬機所管理的內存中最大的一塊。Java堆是被所有線程共享的一塊內存區域,在虛擬機啟動時創建。此內存區域的唯一目的就是存放對象實例,幾乎所有的對象實例都在這里分配內存。
  •     從內存回收的角度來看,由于現在的收集器基本都采用分代收集算法,所以Java堆中還可以細分為:新生代和老年代;再細致一點的有Eden空間、From Survivor空間、To Survivor空間等。
  •     從內存分配的角度來看,線程共享的Java堆中可能劃分出多個線程私有的分配緩沖區(Thread Local Allocation Buffer,TLAB)。不過無論如何劃分,都與存放內容無關,無論哪個區域,存儲的仍然都是對象實例。
  •     進一步劃分的目的是為了更好地回收內存,或者更快地分配內存。
  •     根據Java虛擬機規范的規定,Java堆可以處于物理上不連續的內存空間中,只要邏輯上是連續的即可。在實現時,既可以實現成固定大小的,也可以是可擴展的,不過當前主流的虛擬機都是按照可擴展來實現的(通過 -Xmx(最大)和 -Xms(最小)控制)。如果在堆中沒有內存完成實例分配,并且堆也無法再擴展時,將會拋出OutOfMemoryError異常。

方法區:方法區與Java堆一樣,是各個線程共享的內存區域,它用于存儲已被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯后的代碼等數據。雖然Java虛擬機規范把方法區描述為堆的一個邏輯部分,但是它卻有一個別名叫做Non-Heap(非堆),目的應該是與Java堆區分開來。
  •     方法區與永久代本質上并不等價,僅僅是因為HotSpot虛擬機的設計團隊選擇把GC分代收集擴展至方法區,或者說使用永久代來實現方法區而已,這樣HotSpot的垃圾收集器可以像管理Java堆一樣管理這部分內存,能夠省去專門為方法區編寫內存管理代碼的工作。對于其他虛擬機(如BEA JRockit、IBM J9等)來說是不存在永久代這個概念的。原則上,如何實現方法區屬于虛擬機實現細節,不受虛擬機規范約束,但使用永久代來實現方法區,現在看來并不是一個好主意,因為這樣更容易遇到內存溢出問題(永久代有 -XX:MaxPermSize的上限,J9和JRockit只要沒有觸碰到進程可用內存的上限,例如32位系統中的4GB,就不會出現問題)。JDK1.7的HotSpot中,已經把原本放在永久代的字符串常量池移出。
  •     根據Java虛擬機規范的規定,當方法區無法滿足內存分配需求時,就拋出OutOfMemoryError異常。

運行時常量池運行時常量池方法區的一部分。Class文件中除了有類的版本、字段、方法、接口等描述信息外,還有一項信息是常量池,用于存放編譯期生成的各種字面量和符號引用,這部分內容在類加載后進入方法區的運行時常量池中存放。
    因為運行時常量池是方法區的一部分,所以自然受到方法區內存的限制,當常量池無法再申請到內存時會拋出OutOfMemoryError異常。

直接內存:直接內存并不是虛擬機運行時數據區的一部分,也不是Java虛擬機規范中定義的內存區域。但是這部分內存也被頻繁的使用,而且也可能導致OutOfMemoryError異常出現。
    在JDK1.4中新加入了NIO(New Input/Output)類,引入了一種基于通道(Channel)與緩沖區(Buffer)的I/O方式,它可以使用Native函數庫直接分配堆外內存,然后通過一個存儲在Java堆中的DirectByteBuffer對象作為這塊內存的引用進行操作。這樣能在一些場景中顯著提高性能,因為避免了在Java堆和Native堆中來回復制數據。

HotSpot虛擬機對象揭秘
   對象的創建:(僅限于普通Java對象,不包括數組和Class對象等)
  1.         虛擬機遇到一條new指令時,首先將去檢查這個指令的參數是否能再常量池中定位到一個類的符號引用,并且檢查這個符號引用代表的類是否已經被加載、解析和初始化過。如果沒有,那必須先執行相應的類加載過程。在類加載檢查通過后,接下來虛擬機將為新生對象分配內存。對象所需內存的大小在類加載完成后便可完全確定,為對象分配空間的任務等同于把一塊確定大小的內存從Java堆中劃分出來。劃分方式:①指針碰撞(Bump the Pointer)。如果Java堆中的內存是絕對規整的,所有用過的內存都放在一邊,空閑的放在另一邊,中間放著一個指針作為分界點的指示器,那分配內存就僅僅是把那個指針向空閑那邊挪動一段與對象大小相等的距離,這種分配方式稱為“指針碰撞”。空閑列表(Free List):如果Java堆中的內存并不是規整的,已使用的內存和空閑的內存相互交錯,那就沒辦法簡單的進行指針碰撞了,虛擬機就必須維護一個列表,記錄上哪些內存塊是可用的,在分配的時候從列表中找到一塊足夠大的空間劃分給對象實例,并更新列表上的記錄。
  2.         選擇哪種分配方式由Java堆是否規整決定,而Java堆是否規整又有所采用的垃圾收集器是否帶有壓縮整理功能決定。分配內存方式:①是對分配內存空間的動作進行同步處理——實際上虛擬機采用CAS配上失敗重試的方式保證更新操作的原子性。是把內存分配的動作按照線程劃分在不同的空間之中進行,即每個線程在Java堆中預先分配一小塊內存,稱為本地線程分配緩沖(Thread Local Allocation Buffer,TLAB)。哪個線程要分配內存,就在哪個線程的TLAB上分配,只有TLAB用完并分配新的TLAB時,才需要同步鎖定。
  3.         內存分配完成后虛擬機需要將分配到的內存空間都初始化為零值(不包括對象頭),如果使用TLAB,這一工作過程也可以提前至TLAB分配時進行。這一步操作保證了對象的實例字段在Java代碼中可以不賦初始值就直接使用,程序能訪問到這些字段的數據類型所對應的零值。
  4.         接下來,虛擬機要對對象進行必要的設置,例如這個對象是哪個類的實例、如何才能找到類的元數據信息、對象的哈希碼、對象的GC分代年齡等信息。這些信息存放在對象的對象頭(Object Header)之中。根據虛擬機當前的運行狀態的不同,如是否啟用偏向鎖等,對象頭會有不同的設置方式。
  5.            在上面工作都完成之后,從虛擬機的視角來看,一個新的對象已經產生了,但從Java的視角來看,對象創建才剛開始——<init>方法還沒執行,所有的字段還都是,所以一般來說執行new指令之后會接著執行<init>方法,這樣一個真正可用的對象才算完全產生出來。

  對象的內存布局:在HotSpot虛擬機中,對象在內存中存儲的布局可與分為3塊區域:對象頭(Object Header)、實例數據(instanceData)、和對齊填充(Padding)。
  • 對象頭:對象頭包括兩部分信息,第一部分用于存儲對象自身的運行時數據,如哈希碼(HashCode)、GC分代年齡、鎖狀態標志、線程持有的鎖、偏向線程ID、偏向時間戳等,這部分數據的長度在32位64位的虛擬機(未開啟壓縮指針)中分別為32bit64bit,官方稱它為“Mark Word”。對象需要存儲的數據有很多,其實已經超出了32位、64位BitMap結構所能記錄的限度,但是對象頭信息是與對象自身定義的數據無關的額外存儲成本,考慮到虛擬機的空間效率,Mark Word被設計成一個非固定的數據結構以便在極小的空間內存儲盡量多的信息,它會根據對象的狀態復用自己的存儲空間。
  對象的訪問定位::Java程序需要通過棧上的 reference 數據來操作堆上的具體對象。由于 reference 類型在Java虛擬機規范中只規定了一個指向對象的引用,并沒有定義這個引用應該通過何種方式去定位、訪問堆中的對象的具體位置,所以對象訪問方式也是取決于虛擬機實現而定的。 目前主流的訪問方式有 使用句柄 和 直接指針 兩種。
  • 如果使用句柄訪問的話,那么Java 堆中將會劃分出一塊內存來作為 句柄池, reference 中存儲的就是對象的句柄地址,而句柄中包含了對象實例數據與類型數據各自的具體地址信息。
  • 如果使用直接指針訪問的話,那么Java堆對象的布局中就必須考慮如何放置訪問類型數據的相關信息,而 reference 中存儲的直接就是對象地址。
  • 這兩種對象訪問方法各有優勢:①使用句柄訪問的最大好處就是 reference 中存儲的是穩定的句柄地址,在對象被移動(垃圾收集時移動對象是非常普遍的行為)時只會改變句柄池中的實例數據指針,而 reference 本身不需要修改;②使用直接指針訪問方式的最大好處就是速度更快,它節省了一次指針定位的時間開銷。

向AI問一下細節

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

AI

冀州市| 彰化县| 前郭尔| 右玉县| 镇赉县| 阳信县| 阿城市| 黄陵县| 凤凰县| 怀仁县| 马关县| 七台河市| 沛县| 梧州市| 迁安市| 万宁市| 保定市| 玉环县| 越西县| 桑日县| 乌拉特前旗| 兖州市| 赤壁市| 铜梁县| 钦州市| 泗水县| 静乐县| 子洲县| 陆川县| 缙云县| 朔州市| 中方县| 红安县| 图片| 贵阳市| 淮滨县| 金寨县| 沙田区| 长葛市| 塔城市| 上杭县|