關于虛擬機棧的理解

虛擬機棧

虛擬機棧出現的背景

由于跨平臺性的設計,Java的指令都是根據棧來設計的. 不同平臺CPU架構不同,所以不能設置為基于寄存器的

優點是跨平臺,指令集小,編譯器容易實現,缺點是性能下降,實現同樣的功能需要更多的指令.


有不少Java開發人員一提到Java內存結構,就會非常粗粒度地將JVM中的內存區理解為僅有Java堆(Heap)和Java棧(stack)? 為什么

內存中的棧與堆

棧是運行時的單位,而堆是存儲的單位
即: 棧解決程序的運行問題,即程序如何執行,或者說如何處理數據.
堆: 堆解決的是數據的存儲的問題,即數據怎么放,放在哪兒.


比喻

java 虛擬機棧是什么?

java虛擬機棧(java virtual machine stack)早期,也叫java棧
每個線程在創建是都會創建一個虛擬機棧, 其 內部保存一個個的棧楨(stack Frame)對應著一次次的Java方法調用.

是線程私有的

聲明周期

生命周期和線程一致.

作用

  • 主管java程序的運行,它保存的方法的局部變量(8種基本數據類型,對象的引用地址),部分結果,并參與方法的調用和返回.
  • 局部變量 vs 成員變量(或屬性)
  • 基本數據變量 vs 引用類型變量(類,數組,接口)

實例

package com.atguigu.java5;/*** ClassName: StackTest <br/>* Description: StackTest <br/>* Date: 2020-10-23 10:36 <br/>* <br/>** @author * @version 產品版本信息 2020年10月23日10:36分 新建<br/>* <p>* 修改記錄* @email * @project study_note_01* @package com.atguigu.java5*/
public class StackTest {public static void main(String[] args) {StackTest test = new StackTest();test.methodA();}public void methodA(){int i = 10;int j = 20;methodB();}public void methodB(){int k = 30;int m = 40;}
}

分析一波

棧的特點(優點)

  • 棧是一種快速有效的分配存儲方式,訪問速度僅此云程序計數器.
  • JVM 直接對 Java棧的操作只有兩個:
    • 每個方法執行,伴隨著進棧(入棧,壓棧)
    • 執行結束后的出棧工作
  • 對于棧來說不存在垃圾回收問題
    • GC ; OOM ;

棧: 先入后出 子彈夾 FILO

隊列: 先入先出 FIFO

面試題: 開發中遇到的異常有哪些

棧可能出現的異常

  • java 虛擬機規范允許java棧的大小是動態的或者是固定不變的
    • 如果采用固定大小的java虛擬機棧,那每一個線程的Java虛擬機棧容量可以在線程創建的時候獨立選定.如果線程請求分配的棧容量超過Java虛擬機棧允許的最大容量,Java虛擬機將會拋出一個StackOverflowError異常.
    • 如果Java虛擬機可以動態擴展,并且在嘗試擴展的時候無法申請到足夠的內存,或者在創建新的線程時沒有足夠的內存區創建對應的虛擬機棧,那Java虛擬機將會拋出一個OutOfMemoryError異常

設置內存中的棧的大小

package com.atguigu.java5;/*** ClassName: StackErrorTest <br/>* Description: StackErrorTest <br/>* Date: 2020-10-23 11:01 <br/>* <br/>** @author yufengming* @version 產品版本信息 2020年10月23日11:01分 *  新建<br/>* <p>* 修改記錄* @email * @project study_note_01* @package com.atguigu.java5* 默認情況下: count:11420* 設置棧的大小: -Xss 256k:*/
public class StackErrorTest {private static int count = 1;public static void main(String[] args) {System.out.println(count);count++;main(args);}
}

11410
11411
11412
Exception in thread "main" java.lang.StackOverflowErrorat sun.nio.cs.UTF_8$Encoder.encodeLoop(UTF_8.java:691)at java.nio.charset.CharsetEncoder.encode(CharsetEncoder.java:579)at sun.nio.cs.StreamEncoder.implWrite(StreamEncoder.java:271)at sun.nio.cs.StreamEncoder.write(StreamEncoder.java:125)at java.io.OutputStreamWriter.write(OutputStreamWriter.java:207)at java.io.BufferedWriter.flushBuffer(BufferedWriter.java:129)at java.io.PrintStream.write(PrintStream.java:526)at java.io.PrintStream.print(PrintStream.java:597)at java.io.PrintStream.println(PrintStream.java:736)at com.atguigu.java5.StackErrorTest.main(StackErrorTest.java:20)

棧的存儲單位

棧中存儲什么?

  • 每個線程都有自己的棧,棧中的數據都是以棧楨(Stack Frame)的格式存在
  • 在這個線程上正在執行的每個方法都各自對應一個棧楨(Stack Frame).
  • 棧楨是一個內存區塊,是一個數據集,維系著方法執行過程中的各種數據信息.

復習

  • OOP的基本概念: 類,對象
  • 類中基本結構: field(屬性,字段,域),method

棧運行原理

  • JVM 直接對Java棧的操作只有兩個,就是對棧楨的壓棧出棧,遵循"先進后出"/"后進先出"原則
  • 在一條活動線程中,一個時間點上,只會有一個活動的棧楨.即只有當前正在執行的方法的棧楨(棧頂棧楨)是有效的,這個棧楨被稱為當前棧楨(current frame),與當前棧楨相對應的方法就是當前方法(current method),定義這個方法的類就是當前類(current class)
  • 執行引擎運行的所有字節碼指令只針對當前棧楨進行操作
  • 如果在該方法中調用了其他方法,對應的新的棧楨會被創建出來,放在棧的頂端,成為新的當前幀.

當前棧楨,一直在移動

依次執行

  • 不同線程中所包含的棧楨是不允許存在相互引用的,即不可能在一個棧楨之中引用另外一個線程的棧楨.
  • 如果當前方法調用了其他方法,方法返回之際,當前棧楨會傳回此方法的執行結果給前一個棧楨,接著,虛擬機會丟棄當前棧楨,使得前一個棧楨重新成為當前棧楨.
  • Java方法有兩種返回函數的方式,一種是正常的函數返回,使用return指令;另外一種是拋出異常.不管使用哪種方式,都會導致棧楨被彈出.

棧楨內部結構

在虛擬機這塊兒,有錯誤的帖子很多,你不能全信

垃圾回收算法

局部變量表

  • 局部變量表也被稱之為局部變量數組或本地變量表
  • **定義為一個數字數組,主要用于存儲方法參數和定義在方法體內的局部變量,**這些數據類型包括各類基本數據類型,對象引用(reference),以及returnAddress類型.
  • 由于局部變量表示建立在線程的棧上,是線程的私有數據,因此不存在數據安全問題
  • 局部變量表所需的容量大小是在編譯期確定下來的,并保存在方法Code屬性的maximum local variables 數據項中.在方法運行期間是不會改變局部變量表的大小的.

javap 命令 解析,這個idea具有反編譯功能

idea中jclasslib 插件

  • 方法嵌套調用的次數由棧的大小決定.一般來說,**棧越大,方法嵌套調用次數越多.**對一個函數而言,它的參數和局部變量越多,使得局部變量表膨脹,它的棧楨就越大,以滿足方法調用所需傳遞的信息增大的需求.進而函數調用就會占用更多的棧空間,導致其嵌套調用次數就會減少.
  • **局部變量表中的
  • **.在方法執行時,虛擬機通過使用局部變量表完成參數值到參數變量列表的傳遞過程.**當方法調用結束后,隨著方法棧楨的銷毀,局部變量表也會隨之銷毀.

關于Slot的理解

  • 參數值的存放總是在局部變量數組index0 開始,到數組長度-1 的索引結束.

  • 局部變量表,最基本的存儲單元是Slot(變量槽)

  • 局部變量表中存放編譯期可知的各種基本數據類型(8種),引用類型(reference),returnAddress類型的變量.

  • 在局部變量表里,32位以內的類型只占用一個slot(包括returnAddress類型),64位的類型(long和double)占用兩個slot.

  • byte,short,char 在存儲前被轉換為int,boolean也被轉換為int,0 表示 false,非0 表示 true.

  • long和double 則占據兩個Slot.

  • JVM會為局部變量表中的每一個Slot都分配一個訪問索引,通過這個索引即可成功訪問到局部變量表中指定的局部變量值

  • 當一個實例方法被調用的時候,它的方法參數和方法體內部定義的局部變量將會按照順序被復制到局部變量表中的每一個Slot上

  • 如果需要訪問局部變量表中一個64bit的局部變量值時,只需要使用前一個索引即可.(比如: 訪問long或double類型變量)

  • 如果當前幀是由構造方法或者實例方法創建的,name該對象引用this將會存放在index為0的slot處,其余的參數按照參數表順序繼續排列

4分鐘

構造器中的this,表示當前創建的變量


棧楨中的布局變量表中的槽位是可以重用的,如果一個局部變量過了其作用域,那么在其作用域之后申明的新的局部變量就會很有可能會復用過期局部變量的槽位,從而達到節省資源的目的

變量的分類

按照數據類型:

  1. 基本數據類型
  2. 引用數據類型

按照在類中聲明的位置:

  1. 成員變量: 在使用前都經歷過初始化賦值
  • 使用靜態來修飾的(類變量):
    • linking的prepare階段:給類變量默認賦值 —>
    • initial階段: 給類變量顯示賦值即靜態代碼
  • 實例變量(歸具體的對象所有)
    :隨著對象的創建,會在堆空間中分配實例變量空間,并進行默認賦值
  1. 局部變量: 在使用前,比如要進行顯示賦值,否則,編譯不通過
public void test5Temp(){int num;System.out.println(num);// 錯誤信息,變量num沒有進行賦值(未初始化錯誤)
}

補充說明

  • 在棧楨當中,與性能調優關系最為密切的部分就是前面提到的局部變量表.
    在方法的執行時,虛擬機使用局部變量表完成方法的傳遞.
  • 局部變量表中的變量也是重要的垃圾回收根節點,只要被局部變量表中直接或間接引用的對象都不會被回收.

在靜態的方法當中是不可以引用這個this的

Slot的重復利用

棧楨當中的局部變量表中的槽位是可以重用的,如果一個局部變量過了其作用域,那么在其他作用域之后申明的新的局部變量就很喲與可能會復用過期局部變量的槽位,從而達到節省資源的目的

52 操作數棧(Operate Stack)

這個是數據結構中的一種,先進后出的特點

棧: 可以通過數組或鏈表來實現
棧可以看成滿足特殊條件的數組或者鏈表.


  • 每一個獨立的棧楨當中除了包含局部變量表以外,還包含一個后進獻出(Last-In-First-Out)的操作數棧,也可以稱之為表達式棧(Expression Stack)

  • 操作數棧,在方法執行過程中,根據字節碼指令,往棧中寫入數據或提取數據,即入棧(push)/出棧(pop).

    • 某些字節碼指令將值亞入操作數棧,其余的字節碼指令將操作數取出棧.使用它們后再把結果壓入棧.
    • 比如:執行復制交換,求和等操作.
  • 操組數棧,主要用于保存計算過程的中間計算結果,同時作為計算過程中變量臨時的存儲空間

  • 操作數棧就是JVM執行引擎的一個工作區,當一個方法剛開始執行的時候,一個新的棧楨也會隨之被創建出來,這個方法的操作數棧是空的

  • 每一個操作數棧都會擁有一個明確的棧深度用于存儲數值,其所需的最大深度在編譯期就定義好了,保存在方法的Code屬性中,為Max_stack的值.

  • 棧中的任何一個元素都是可以任意Java數據類型

    • 32bit的類型占用一個棧單位深度
    • 64bit的類型占用兩個棧單位深度
  • 操作數棧并非采用訪問索引的方式來進行數據訪問的,而是只能通過標準的入棧(push)和出棧(pop)操作來完成一次數據訪問.

  • 如果被調用的方法帶有返回值的話,其返回值將會被壓入當期棧楨的操作數棧中,并更新PC寄存器中嚇一跳需要執行的字節碼指令.

  • 操組數棧中元素的數據類型比如與字節碼執行的序列嚴格匹配,這由編譯器在編譯期間進行驗證,同時在類加載過程中的類檢驗階段的數據流分析階段要再次驗證.

  • 另外,我們說Java虛擬機的解釋引擎是基于棧的執行引擎,其中的棧值的就是操作數棧.

動態鏈接(或指向運行時常量池的方法引用)

動態鏈接


方法的調用

在java虛擬機當中,將符號引用轉換為調用方法的直接引用于方法的綁定機制相關

  • 靜態鏈接:
    當一個字節碼文件被裝載進JVM內部時,如果被調用的目標方法在編譯期可知,且運行期保持不變時.這種情況下降調用方法的符號引用轉換為直接引用的過程稱之為靜態鏈接.
  • 動態鏈接:

如果**如果被調用的方法在編譯期無法被確定下來,**也就是說,只能夠在程序運行期將調用方法的符號引用轉換為直接引用,由于這種引用轉換過程具備動態性,因此也就被稱之為動態鏈接.

方法的調用

對應的方法的綁定機制為: 早期綁定(Early Binding) 和晚期綁定(Late Binding). **綁定是一個字段,方法或者類在符號引用被替換為直接引用的過程,這僅僅發生一次.

  • 早期綁定:
    早期綁定就是指被調用的目標方法如果在編譯期可知,且運行期保持不變時,即可將這個方法與所屬的類型進行綁定,這樣一來,由于明確了被調用的目標方法究竟是哪一個,因此也就可以使用靜態鏈接的方式將符號引用轉換為直接引用.
  • 晚期綁定:
    如果被調用的方法在編譯期無法被確定下來,只能夠在程序運行期根據實際的類型綁定相關的方法,這種綁定方式也就被稱之為晚期綁定
    隨著高級語言的橫空出世,類似于Java一樣的基于面向對象的編程語言如今越來越多,盡管這類編程語言在語法風格上存在一定的差別,但是它們彼此之間始終保持著一個共性,那就是都支持封裝\繼承,和多態等面向對象特性,既然這一類的編程語言具備多態特性,那么自然也就具備早期綁定和晚期綁定兩種綁定方式.

Java 中任何一個普通的方法其實都具備虛函數的特征,它們相當于C++語言中的虛函數(C++中則需要使用關鍵字Virtual來進行顯示的定義).如果在Java程序匯總不希望某個方法擁有虛函數的特征時,則可以使用關鍵字final來標記這個方法.

虛方法和非虛方法

非虛方法

  • 如果方法在編譯期就確定了具體的調用版本,這個版本在運行時是不可變的.這樣的方法稱為非虛方法
  • 靜態方法,私有方法,final方法,實例構造器,父類方法都是非虛方法.
  • 其他方法稱為虛方法.

多態的使用前提:
1 類的繼承關系
2 方法的重寫

虛擬機中提供了一些幾條方法調用指令:

  • 普通調用指令:
    1. invokestatic: 調用靜態方法,解析階段確定唯一方法版本
    2. invokespecial: 調用方法,私有及父類方法,解析階段確定唯一方法版本
    3. invokevirtual: 調用所有虛方法
    4. invokeinterface: 調用接口方法
  • 動態調用指令:
    5. invokedynamic: 動態解析出需要調用的方法,然后執行

前4條指令固化在虛擬機內部,方法的調用執行不可人為干預,而invokedynamic指令則支持由用戶確定方法版本.其中invokestatic指令和invokespecial指令調用的方法稱為非虛方法,其余的(final修飾的除外)稱為虛方法.

練習一下

package com.atguigu.java6;/**\*解析*/
class Father{public Father() {System.out.println("father的構造器~");}public static void showStatic(String str) {System.out.println("Father"+str);}public final void showFinal() {System.out.println("father show final!");}public void showCommon() {System.out.println("father 普通方法!");}}
public class Son extends Father{public Son() {super();}public Son(int age) {this();}/*** 不是重寫的父類方法* @param str*/public static void showStatic(String str) {System.out.println(str);}private void showPrivate(String str) {System.out.println("son private"+str);}public void show() {showStatic("autaied.com");super.showStatic("ggoaset");showPrivate("hellow!");super.showCommon();showFinal();showCommon();info();//        MethodInterface in = null;
//        in.methodA();}public void info() {}public static void main(String[] args) {new Son().show();}
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/455154.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/455154.shtml
英文地址,請注明出處:http://en.pswp.cn/news/455154.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

抓取各個瀏覽器引擎關鍵字,,百度學術關鍵字

百度學術 $list_arr getbaiduxueshu($row[name]); $list_arr explode((,$list_arr); $list_arr explode(),$list_arr[1]); $list_arr json_decode($list_arr[0]); $list_arr $list_arr->s; //百度學術平臺熱詞地址function getbaiduxueshu($keyname 100){ $url http:…

wave格式分析,wave音頻文件格式分析配程序

wav文件格式分析詳解 程序如上一篇博文 一、綜述 WAVE文件作為多媒體中使用的聲波文件格式之一&#xff0c;它是以RIFF格式為標準的。RIFF是英文Resource Interchange File Format的縮寫&#xff0c;每個WAVE文件的頭四個字節便是“RIFF”。 WAVE文件是由若干個Chunk組成…

poi設置word表格單元格寬度_java poi如何設置word的頁面的大小和水平方向?

展開全部你好&#xff0c;試試以下代碼行不行。packagecom.sample;importjava.awt.color;importjava.io.fileoutputstream;importjava.io.ioexception;importcom.lowagie.text.cell;importcom.lowagie.text.document;importcom.lowagie.text.documentexception;importcom.lowag…

時間通用方法

import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date;import org.apache.commons.lang3.time.DateFormatUtils;/** * 日期工具類, 繼承org.apache.commons.lang.time.DateUtils類 */ public class DateUtils extends org.apache.commo…

Python-MongoDB的驅動安裝、升級

安裝pip&#xff0c;并通過此來安裝pymongo–Python mongodb驅動 1、下載pip安裝包&#xff0c;下載地址&#xff1a;http://pypi.python.org/packages/source/p/pip/pip-1.0.2.tar.gz#md547ec6ff3f6d962696fe08d4c8264ad49 2、解壓安裝&#xff1a; tar -zxf pip.1.0.2.tar.gz…

python5_python5

python2&python31.python2中print可加括號可不加括號&#xff0c;python3中print一定要加括號。2.python2中有range(),也有xrange(),python中只有range()。生成器。3.Python2中raw_input(),python3中input()。,,is賦值比較是否相等is 比較內存地址&#xff0c;id(內容)li1[…

單例設計模式1

單例 所謂單例設計模式,即時采取一定的方法保證在整個軟件系統當中,對于某個類只能存在一個對象實例,并且該類只提供一個其對象實例的方法(靜態方法) 惡漢式 優缺點說明: 優點:這種寫法比較簡單,就是在類裝載的時候就完成實例化.避免了線程同步問題 缺點: 在類裝載的時候就…

SJXXX串口擴展芯片 4串口芯片 UART串口芯片

SJXX串口擴展芯片1 概述SJ000是一款具備I2C總線/SPI總線/UART接口的四通道異步收發器件&#xff0c;通過模式選擇使得該器件工作于以上任何一種主接口模式下。器件的四個通道UART可提供高達2Mbps的數據率&#xff0c;低功耗模式和睡眠電流。每個通道含有一個接收器和一個發送器…

MPLS服務合同到期了,是否該續簽?

當考慮是否要更新現有MPLS服務合同以及續簽多久時&#xff0c;你需要著眼于從價格到部署速度的方方面面。簡而言之&#xff0c;如果你還沒有獲取一些與軟件定義廣域網有關技術的經驗&#xff0c;即使用寬帶或取代MPLS服務&#xff0c;那么你就沒辦法在未來幾個月之內棄用MPLS。…

oracle rds 運維服務_從運維的角度分析使用阿里云數據庫RDS的必要性–你不應該在阿里云上使用自建的MySQL/SQL Server/Oracle/PostgreSQL數據庫...

開宗明義&#xff0c;你不應該在阿里云上使用自建的MySQL or SQL Server數據庫&#xff0c;對了&#xff0c;還有Oracle or PostgreSQL數據庫。云數據庫 RDS(Relational Database Service)是一種穩定可靠、可彈性伸縮的在線數據庫服務。基于飛天分布式系統和全SSD盤高性能存儲&…

單例設計模式2

惡漢式(靜態代碼塊兒) 優缺點說明: 這種方式和上面的相似,只不過將類實例化的過程放在了靜態代碼塊中,也是在類裝載的時候,就執行靜態代碼塊兒中的代碼,初始化類的實例.優缺點和上面是一樣的. 結論: 這種單例模式可用,可能 造成內存浪費 代碼演示 package com.atguigu.pri…

FLV文件格式解析

FLV&#xff08;Flash Video&#xff09;是現在非常流行的流媒體格式&#xff0c;由于其視頻文件體積輕巧、封裝播放簡單等特點&#xff0c;使其很適合在網絡上進行應用&#xff0c;目前主流的視頻網站無一例外地使用了FLV格式。另外由于當前瀏覽器與Flash Player緊密的結合&am…

華院數據宣曉華:傳統零售商轉型電商需攻克大數據三關

現在電商發展起來的節奏&#xff0c;使得大眾更相信馬云所言“五年內將沒有線下銷售”的可信度。面對這樣的轉變最該緊張的似乎是傳統零售商了&#xff0c;日前在中美創新鏈接——大數據專題研討會上&#xff0c;華院數據創始人、董事長宣曉華談了傳統零售商在轉型過程中遭遇的…

部署到gcp_GCP 網絡系統Andromeda --- 概述篇

這個系列總共有三篇&#xff0c;分別在&#xff1a;肖宏輝&#xff1a;GCP 網絡系統Andromeda --- 概述篇肖宏輝&#xff1a;GCP 網絡系統Andromeda --- 控制面肖宏輝&#xff1a;GCP 網絡系統Andromeda --- 數據面最近看了Google在2018年的一篇NSDI文章&#xff0c;介紹他們的…

單例設計模式-懶漢式(線程不安全)

懶漢式(線程不安全) 優缺點說明 起到了Lazy Loading的效果,但是只能在單線程下使用 如果在多線程下, 一個線程進入if(singleton null)判斷 語句塊,還未來得及往下執行,另一個線程也通過了這個判斷語句,這時便會產生多個實例. 所以在多線程的環境下,不可使用種方式 結論:在…

南海發展大數據產業 建設新型智慧城市

今天(9月5日)上午,佛山市南海區將迎來一大盛事——“南海大數據及工業互聯網創新應用工作推進會”(以下簡稱“推進會”)召開,南海將與阿里巴巴、騰訊以及三大通信運營商等互聯網、大數據巨頭簽訂21個大數據建設亮點項目。同時,為吸引更多大數據產業集聚,南海將在推進會上同步發…

AMR音頻編碼器概述及文件格式分析

全稱Adaptive Multi-Rate&#xff0c;自適應多速率編碼&#xff0c;主要用于移動設備的音頻&#xff0c;壓縮比比較大&#xff0c;但相對其他的壓縮格式質量比較差&#xff0c;由于多用于人聲&#xff0c;通話&#xff0c;效果還是很不錯的。 一、分類 1. AMR: 又稱為AMR-NB&am…

查詢自己OpenGL的版本信息

GLvoid PrintVersion() {const GLubyte* name glGetString(GL_VENDOR); //返回負責當前OpenGL實現廠商的名字const GLubyte* biaoshifu glGetString(GL_RENDERER); //返回一個渲染器標識符&#xff0c;通常是個硬件平臺const GLubyte* OpenGLVersion glGetStr…

airpod藍牙耳機音量大解決辦法_關于AirPods的常見問題匯總 全面了解蘋果AirPods無線耳機...

小編帶來關于AirPods必知的24個問題&#xff0c;全面了解蘋果AirPods無線耳機。蘋果決定在iPhone7中拋棄3.5毫米耳機接口&#xff0c;這引發了許多爭議和不解。蘋果這樣做的原因部分在于&#xff0c;希望人們轉而使用無線耳機。因此蘋果也推出了自主的無線耳機AirPods。對于無線…

單例設計模式-懶漢式(線程安全)

懶漢式(線程安全) 有缺點說明 解決了線程不安全問題 效率太低了,每個線程在想獲得類的實例時候,執行getInstance()方法都要進行同步.而其實這個方法只執行了一次實例化代碼就夠了,后面的想獲取該類實例,直接return就行了.方法進行同步效率太低 結論: 在實際開發中,不推薦使用…