日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

在没有任何数据时进行无效的读取尝试。_技术转载——JVM运行时内存是怎么分布的?...

發(fā)布時間:2024/9/15 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 在没有任何数据时进行无效的读取尝试。_技术转载——JVM运行时内存是怎么分布的?... 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

寫在前面:2020年面試必備的Java后端進(jìn)階面試題總結(jié)了一份復(fù)習(xí)指南在Github上,內(nèi)容詳細(xì),圖文并茂,有需要學(xué)習(xí)的朋友可以Star一下!

GitHub地址:https://github.com/abel-max/Java-Study-Note/tree/master

寄存器中的內(nèi)存最小速度最快,硬盤容量最大,速度最小,cup的第三級緩存是共享內(nèi)存。

對于一個在同一行的數(shù)據(jù)XY,會被同時加載進(jìn)CPU,這個現(xiàn)象叫cache line緩存行對齊, 緩存行對齊具體內(nèi)容可以看看這篇文章 如果左邊的CPU核心加載了X并進(jìn)行修改,但是此時并沒有將數(shù)據(jù)寫回進(jìn)主內(nèi)存,或者是第三級緩存,此時右邊的CPU核心將X讀進(jìn),并修改,此時就會產(chǎn)生數(shù)據(jù)不一致的情況。對于左邊修改了數(shù)據(jù)右邊如何才能知道,這是硬件層級需要解決的。 多線程一致性的硬件支持有以下幾種方式。

  • 鎖總線的方式。總線鎖會鎖住bus總線,使得其他CPU不能訪問內(nèi)存中的其他地址,因而效率極低。CPU的共享內(nèi)存都是通過
  • MESI(英特爾CPU) 等等之類的緩存一致性協(xié)議,相對于總線鎖的方式MESI的性能好很多。M: 被修改(Modified) 當(dāng)一個值被加載到一個CPU內(nèi)存中,同時這個CPU修改了這個值,則用Modified來表示,意味著在未來某個時刻會將這個值寫入進(jìn)主存。E: 獨享的(Exclusive) 只有當(dāng)前的CPU才能加載這個數(shù)據(jù),就屬于Exclusive獨享的值。S: 共享的(Shared) 當(dāng)多個CPU讀取了同一個值,則用Shared來表示。I: 無效的(Invalid) 當(dāng)前CPU讀取的值已經(jīng)被修改過了,則這個值是無效的用Invalid表示,以為這未來某個時刻會從主存中讀取這個值。
  • 在特定情況下CPU會進(jìn)行指令重排,以保證高效的執(zhí)行。CPU如何保證特定的情況下不不亂序執(zhí)行。通過內(nèi)存屏障來保證指令的有序性。下面是三種CPU指令內(nèi)存屏障指令。sfence:在sfence指令前的寫操作必須在sfence后寫操作完成之前完成操作。即在兩次寫操作之間加個屏障使其不能被重排。lfence:在lfence指令前的讀操作必須在lfence后的讀操作完成之前完成操作。即在兩次讀操作之間加個屏障使其不能被重排。mfence:在mfence指令前的讀寫操作必須在mfence的讀寫操作完成之前完成操作。即在一次讀一次寫和另一次讀和一次寫之間加一個屏障使其不能被重排。CPU保證有序執(zhí)行除了可以使用mfence,還可以使用jvm內(nèi)存屏障,對上面的CPU內(nèi)存屏障進(jìn)行組合,有如下四種屏障loadload屏障,對于這樣的語句Load1; LoadLoad; Load2, 在Load2及后續(xù)讀取操作要讀取的數(shù)據(jù)被訪問前,保證Load1要讀取的數(shù)據(jù)被讀取完畢。storestore屏障,對于這樣的語句Store1; StoreStore; Store2,在Store2及后續(xù)寫入操作執(zhí)行前,保證Store1的寫入操作對其它處理器可見。loadstore屏障,對于這樣的語句Load1; LoadStore; Store2,在Store2及后續(xù)寫入操作被刷出前,保證Load1要讀取的數(shù)據(jù)被讀取完畢。storeload屏障,對于這樣的語句Store1; StoreLoad; Load2,在Load2及后續(xù)所有讀取操作執(zhí)行前,保證Store1的寫入對所有處理器可見。
  • Runtime Data Area and Instruction Set

    jvms 2.4 2.5

    指令集分類

  • 基于寄存器的指令集
  • 基于棧的指令集 Hotspot中的Local Variable Table = JVM中的寄存器
  • Runtime Data Area

    PC 程序計數(shù)器 Program Counter

    Each Java Virtual Machine thread has its own pc (program counter) register.

    每個Java虛擬機線程都有自己的程序計數(shù)器的存儲空間。

    At any point, each Java Virtual Machine thread is executing the code of a single method, namely the current method for that thread.

    在任何時候,每個Java虛擬機線程都在執(zhí)行單個方法的代碼,即該線程的當(dāng)前方法。

    If that method is not native , the pc register contains the address of the Java Virtual Machine instruction currently being executed.

    如果該方法不是本機方法,則pc寄存器包含當(dāng)前正在執(zhí)行的Java虛擬機指令的地址。

    存放指令位置

    虛擬機的運行,類似于這樣的循環(huán):

    while( not end ) {取PC中的位置,找到對應(yīng)位置的指令;執(zhí)行該指令;PC ++; }

    JVM Stack

    Each Java Virtual Machine thread has a private Java Virtual Machine stack, created at the same time as the thread.

    每個Java虛擬機線程都有一個私有Java虛擬機堆棧,與該線程同時創(chuàng)建。

    A Java Virtual Machine stack stores frames

    每個Java虛擬機存儲的都是棧幀

  • Frame - 每個方法對應(yīng)一個棧幀Local Variable Table 局部變量Operand Stack 操作數(shù)堆 當(dāng)一個方法剛剛開始執(zhí)行時,其操作數(shù)棧是空的,隨著方法執(zhí)行和字節(jié)碼指令的執(zhí)行,會從局部變量表或?qū)ο髮嵗淖侄沃袕?fù)制常量或變量寫入到操作數(shù)棧,再隨著計算的進(jìn)行將棧中元素出棧到局部變量表或者返回給方法調(diào)用者,也就是出棧/入棧操作。一個完整的方法執(zhí)行期間往往包含多個這樣出棧/入棧的過程。Dynamic Linking 動態(tài)鏈接 所謂動態(tài)鏈接就是指向運行時常量池的那個鏈接,然后看看指向的那個鏈接有沒有解析,如果已經(jīng)解析直接拿過來使用,沒有解析嘗試進(jìn)行解析。表明這個方式叫什么,什么類型等等信息。比如在a()方法中調(diào)用了一個b()方法,在a的應(yīng)用肯定有個b()但是b的具體內(nèi)容在哪里是dynamic linking去獲取。return address a() -> b(),方法a調(diào)用了方法b, b方法的返回值放在什么地方
  • Heap

    The Java Virtual Machine has a heap that is shared among all Java Virtual Machine threads.

    java 虛擬機有個所有線程共享的堆內(nèi)存。

    The heap is the run-time data area from which memory for all class instances and arrays is allocated.

    堆是運行時數(shù)據(jù)區(qū),從中分配所有類實例和數(shù)組的內(nèi)存。

    Method Area

    The Java Virtual Machine has a method area that is shared among all Java Virtual Machine threads.

    Java虛擬機具有一個在所有Java虛擬機線程之間共享的方法區(qū)域。

    It stores per-class structures

    存儲每個類的結(jié)構(gòu)

  • Perm Space (<1.8) 字符串常量位于PermSpace FGC不會清理 大小啟動的時候指定,不能變
  • Meta Space (>=1.8) 字符串常量位于堆 會觸發(fā)FGC清理 不設(shè)定的話,最大就是物理內(nèi)存
  • Runtime Constant Pool

    A run-time constant pool is a per-class or per-interface run-time representation of the constant_ pool table ina class file

    Native Method Stack

    An implementation of the Java Virtual Machine may use conventional stacks called native method stacks

    Direct Memory

    JVM可以直接訪問的內(nèi)核空間的內(nèi)存 (OS 管理的內(nèi)存) NIO , 提高效率,實現(xiàn)zero copy

    上面的內(nèi)容總結(jié)起來就是下面這張圖

    每個線程都有自己的棧內(nèi)存,里面存放的是棧幀,如果有調(diào)用native方法就還存在native method stack,還有自己program counter程序計數(shù)器,用來記錄每條指令的執(zhí)行,當(dāng)CPU切換線程的時候方便知道之前線程執(zhí)行到哪條指令,所有線程共享堆內(nèi)存和方法區(qū),方法區(qū)有兩種實現(xiàn),在jdk8之前方法區(qū)叫PermGen永久代,jdk8及其以后的版本都叫Meta Space 元數(shù)據(jù)區(qū)。

    棧幀:A frame is used to store data and partial results, as well as to perform dynamic linking, return values for methods, and dispatch exceptions.

    棧幀是用來存儲數(shù)據(jù)部分結(jié)果,和執(zhí)行動態(tài)鏈接,返回方法的值和處理異常調(diào)度。

    我們看一下一個簡單的方法的執(zhí)行過程的棧幀是怎么樣的。

    pubilc class Test1{pubilc static void main(String [] args){Test h = new Test();h.m1();} }pubilc class Test{public void m1(){int i = 200;} }

    編譯后的Test1字節(jié)碼為:

    0 new #2 <com/yhx/Test> 3 dup 4 invokespcial #3<com/yhx/Test<init>> 7 istore_1 8 iload_1 9 invokespcial #3<com/yhx/Test<m1>> 12 return

    對應(yīng)Test字節(jié)碼為:

    0 ipush 200 3 istore_1 4 return

    我我們看一下執(zhí)行過程,在含有主方法的字節(jié)碼中,首先執(zhí)行一個new指令。new一個對象的話,包括三個操作:

  • 首先開辟一個內(nèi)存空間放在棧幀中,此時就包含了一個Dynamic Linking 動態(tài)連接的過程要把 Test h = new Test()中的Test類對應(yīng)成這個類內(nèi)存地址;
  • 然后給這個對象的成員變量付出初始值(不是默認(rèn)值);
  • 最后初始化給成員變量一個默認(rèn)值(init)。
  • 我們看上面指令,在這條 invokespcial #3<com/yhx/Test>也就是初始化之前執(zhí)行了一個dup指令,也就是上面初始化對象的是哪個流程執(zhí)行完第二個流程,此時這個對象的成員變量的值如果是引用型的則還是為null,這個dup指令是將main方法棧幀中Operand Stacks的(如上圖)h復(fù)制一份,然后出棧,init操作拿著出棧后的值進(jìn)行初始化操作,這個時候棧內(nèi)的對象引用就變?yōu)槌跏蓟蟮牧恕?接下來就是“istore_1”變量1就是h,將初始化好的內(nèi)存引用賦值給h,然后“iload_1”把變量1加載進(jìn)本地變量表。

    來源:https://www.tuicool.com/articles/YZnYZvI

    總結(jié)

    以上是生活随笔為你收集整理的在没有任何数据时进行无效的读取尝试。_技术转载——JVM运行时内存是怎么分布的?...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。