<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    Java 8 的內存結構

    VSole2022-03-10 14:37:13

    java8內存結構圖

    虛擬機內存與本地內存的區別

    Java虛擬機在執行的時候會把管理的內存分配成不同的區域,這些區域被稱為虛擬機內存,同時,對于虛擬機沒有直接管理的物理內存,也有一定的利用,這些被利用卻不在虛擬機內存數據區的內存,我們稱它為本地內存,這兩種內存有一定的區別:

    JVM內存

    • 受虛擬機內存大小的參數控制,當大小超過參數設置的大小時就會報OOM

    本地內存

    • 本地內存不受虛擬機內存參數的限制,只受物理內存容量的限制
    • 雖然不受參數的限制,但是如果內存的占用超出物理內存的大小,同樣也會報OOM

    java運行時數據區域

    java虛擬機在執行過程中會將所管理的內存劃分為不同的區域,有的隨著線程產生和消失,有的隨著java進程產生和消失,根據《Java虛擬機規范》的規定,運行時數據區分為以下一個區域:

    程序計數器(Program Counter Register)

    程序計數器就是當前線程所執行的字節碼的行號指示器,通過改變計數器的值,來選取下一行指令,通過他來實現跳轉、循環、恢復線程等功能。

    • 在任何時刻,一個處理器內核只能運行一個線程,多線程是通過線程輪流切換,分配時間來完成的,這就需要有一個標志來記住每個線程執行到了哪里,這里便需要到了程序計數器。
    • 所以,程序計數器是線程私有的,每個線程都已自己的程序計數器。

    虛擬機棧(JVM Stacks)

    虛擬機棧是線程私有的,隨線程生滅。虛擬機棧描述的是線程中的方法的內存模型:

    每個方法被執行的時候,都會在虛擬機棧中同步創建一個棧幀(stack frame)。

    每個棧幀的包含如下的內容

    • 局部變量表
    • 局部變量表中存儲著方法里的java基本數據類型(byte/boolean/char/int/long/double/float/short)以及對象的引用(注:這里的基本數據類型指的是方法內的局部變量)
    • 操作數棧
    • 動態連接
    • 方法返回地址

    方法被執行時入棧,執行完后出棧

    虛擬機棧可能會拋出兩種異常:

    • 如果線程請求的棧深度大于虛擬機所規定的棧深度,則會拋出StackOverFlowError即棧溢出
    • 如果虛擬機的棧容量可以動態擴展,那么當虛擬機棧申請不到內存時會拋出OutOfMemoryError即OOM內存溢出

    本地方法棧(Native Method Stacks)

    本地方法棧與虛擬機棧的作用是相似的,都會拋出OutOfMemoryError和StackOverFlowError,都是線程私有的,主要的區別在于:

    • 虛擬機棧執行的是java方法
    • 本地方法棧執行的是native方法(什么是Native方法?)

    Java堆(Java Heap)

    java堆是JVM內存中最大的一塊,由所有線程共享,是由垃圾收集器管理的內存區域,主要存放對象實例,當然由于java虛擬機的發展,堆中也多了許多東西,現在主要有:

    • 對象實例
    • 類初始化生成的對象
    • 基本數據類型的數組也是對象實例
    • 字符串常量池
    • 字符串常量池原本存放于方法區,jdk7開始放置于堆中。
    • 字符串常量池存儲的是string對象的直接引用,而不是直接存放的對象,是一張string table
    • 靜態變量
    • 靜態變量是有static修飾的變量,jdk7時從方法區遷移至堆中
    • 線程分配緩沖區(Thread Local Allocation Buffer)
    • 線程私有,但是不影響java堆的共性
    • 增加線程分配緩沖區是為了提升對象分配時的效率

    java堆既可以是固定大小的,也可以是可擴展的(通過參數-Xmx和-Xms設定),如果堆無法擴展或者無法分配內存時也會報OOM。

    方法區(Method Area)

    方法區絕對是網上所有關于java內存結構文章爭論的焦點,因為方法區的實現在java8做了一次大革新,現在我們來討論一下:

    方法區是所有線程共享的內存,在java8以前是放在JVM內存中的,由永久代實現,受JVM內存大小參數的限制,在java8中移除了永久代的內容,方法區由元空間(Meta Space)實現,并直接放到了本地內存中,不受JVM參數的限制(當然,如果物理內存被占滿了,方法區也會報OOM),并且將原來放在方法區的字符串常量池和靜態變量都轉移到了Java堆中,方法區與其他區域不同的地方在于,方法區在編譯期間和類加載完成后的內容有少許不同,不過總的來說分為這兩部分:

    類元信息(Klass)

    • 類元信息在類編譯期間放入方法區,里面放置了類的基本信息,包括類的版本、字段、方法、接口以及常量池表(Constant Pool Table)
    • 常量池表(Constant Pool Table)存儲了類在編譯期間生成的字面量、符號引用(什么是字面量?什么是符號引用?),這些信息在類加載完后會被解析到運行時常量池中

    運行時常量池(Runtime Constant Pool)

    • 運行時常量池主要存放在類加載后被解析的字面量與符號引用,但不止這些
    • 運行時常量池具備動態性,可以添加數據,比較多的使用就是String類的intern()方法

    直接內存

    直接內存位于本地內存,不屬于JVM內存,但是也會在物理內存耗盡的時候報OOM,所以也講一下。

    在jdk1.4中加入了NIO(New Input/Putput)類,引入了一種基于通道(channel)與緩沖區(buffer)的新IO方式,它可以使用native函數直接分配堆外內存,然后通過存儲在java堆中的DirectByteBuffer對象作為這塊內存的引用進行操作,這樣可以在一些場景下大大提高IO性能,避免了在java堆和native堆來回復制數據。

    常見問題

    什么是Native方法?

    由于java是一門高級語言,離硬件底層比較遠,有時候無法操作底層的資源,于是,java添加了native關鍵字,被native關鍵字修飾的方法可以用其他語言重寫,這樣,我們就可以寫一個本地方法,然后用C語言重寫,這樣來操作底層資源。當然,使用了native方法會導致系統的可移植性不高,這是需要注意的。

    成員變量、局部變量、類變量分別存儲在內存的什么地方?

    類變量

    • 類變量是用static修飾符修飾,定義在方法外的變量,隨著java進程產生和銷毀
    • 在java8之前把靜態變量存放于方法區,在java8時存放在堆中

    成員變量

    • 成員變量是定義在類中,但是沒有static修飾符修飾的變量,隨著類的實例產生和銷毀,是類實例的一部分
    • 由于是實例的一部分,在類初始化的時候,從運行時常量池取出直接引用或者值,與初始化的對象一起放入堆中

    局部變量

    • 局部變量是定義在類的方法中的變量
    • 在所在方法被調用時放入虛擬機棧的棧幀中,方法執行結束后從虛擬機棧中彈出,所以存放在虛擬機棧中

    由final修飾的常量存放在哪里?

    final關鍵字并不影響在內存中的位置,具體位置請參考上一問題。

    類常量池、運行時常量池、字符串常量池有什么關系?有什么區別?

    類常量池與運行時常量池都存儲在方法區,而字符串常量池在jdk7時就已經從方法區遷移到了java堆中。

    在類編譯過程中,會把類元信息放到方法區,類元信息的其中一部分便是類常量池,主要存放字面量和符號引用,而字面量的一部分便是文本字符,在類加載時將字面量和符號引用解析為直接引用存儲在運行時常量池;

    對于文本字符來說,它們會在解析時查找字符串常量池,查出這個文本字符對應的字符串對象的直接引用,將直接引用存儲在運行時常量池;字符串常量池存儲的是字符串對象的引用,而不是字符串本身。

    什么是字面量?什么是符號引用?

    字面量

    java代碼在編譯過程中是無法構建引用的,字面量就是在編譯時對于數據的一種表示:

    int a=1;//這個1便是字面量
    String b="iloveu";//iloveu便是字面量
    

    符號引用

    由于在編譯過程中并不知道每個類的地址,因為可能這個類還沒有加載,所以如果你在一個類中引用了另一個類,那么你完全無法知道他的內存地址,那怎么辦,我們只能用他的類名作為符號引用,在類加載完后用這個符號引用去獲取他的內存地址。

    例子:我在com.demo.Solution類中引用了com.test.Quest,那么我會把com.test.Quest作為符號引用存到類常量池,等類加載完后,拿著這個引用去方法區找這個類的內存地址。

    虛擬機字面量
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    Java 8 的內存結構
    2022-03-10 14:37:13
    java8內存結構圖虛擬機內存與本地內存的區別Java虛擬機在執行的時候會把管理的內存分配成不同的區域,這些
    安全芯片開放式架構實現了用戶程序和操作系統的分離,降低了應用程序與安全芯片操作系統的耦合性,但同時存在國外壟斷、執行效率低、內存易泄露等弊端。對于搭載了開放式運行環境的安全芯片,面向資源受限所設計的精簡擴展指令集支持與行業應用高度結合,具有基于寄存器的高效指令集解釋執行能力,并具有更好的指令集安全性,可支持多應用融合,有助于打破國外壟斷。
    無論對于Java程序員還是大數據研發人員,JVM是必須掌握的技能之一。Java提供的GC功能可以自動監測對象是否超過作用域等從而達到自動回收內存的目的,可以有效防止內存泄露,有效的使用可用內存。
    清華大學新聞與傳播學院新媒體研究中心將元宇宙定義為整合多種新技術而產生的新型虛實相融的互聯網應用和社會形態,它基于擴展現實技術提供沉浸式體驗,以及數字孿生技術生成現實世界的鏡像,通過區塊技術搭建經濟體系,將虛擬世界與現實世界在經濟系統、社交系統、身份系統上密切融合,并且允許每個用戶進行內容生產和編輯。
    自2008年美國國防部高級研究計劃局(簡稱“DARPA”)正式提出建設國家網絡靶場的構想開始,網絡靶場技術已發展十多年。
    零信任的“問題”
    2022-03-24 18:32:08
    “問題”是一個多義詞,可以理解為負面的意義,如錯誤(Error)、麻煩和困難(Problem)、副作用(Side-effect),也可以理解為開放性的意義,如提問(Question)、題目和課題(Topic)。本文探討零信任的問題,是從宏觀的視角來分析:沒有特別關注零信任的技術細節,重點是試圖追問零信任根本的原理問題;沒有具體討論零信任的實現方法,但是卻希望解構其需求框架。文章重點不在于闡明或立論
    近期,一家互聯網公司在北京發現其求職招聘類App的短信驗證碼接口遭到嚴重攻擊,攻擊次數高達1300余萬次,成功匹配注冊賬號30余萬個,給公司經濟造成損失的同時也威脅了用戶信息安全。
    虛擬機檢測技術整理
    2023-05-11 09:15:35
    第一次嘗試惡意代碼分析就遇到了虛擬機檢測,于是就想著先學習一下檢測的技術然后再嘗試繞過。學習后最終發現,似乎最好的方法不應該是去patch所有檢測方法,而是直接調試并定位檢測函數再繞過。但既然已經研究了天,索性將收集到的資料整理一下,方便后人查找。惡意軟件可以搜索這些文件、目錄或進程的存在。VMware 虛擬機中可能會有如下的文件列表:C:\Program Files\VMware\
    創建Ubuntu虛擬機首先查看可以下載使用的 Ubuntu 鏡像,$?運行成功后,可以看到下面的這些鏡像列表,包含各種版本的。新建一個容器,$?現在有一臺 Ubuntu 18.04 版本的虛擬機在運行,對應的 IP 地址是:192.168.24.5 。如果你不想進入系統內部,也可以通過上述提到的 multipass exce 命令,來操作 Ubuntu 系統。暫停/重啟虛擬機#?刪除/釋放虛擬機使用 delete 命令 刪除虛擬機之后,該虛擬機實際上還是存在了,想要徹底刪除則需要釋放虛擬機
    VSole
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类