主頁 > 後端開發 > JVM--虛擬機堆疊

JVM--虛擬機堆疊

2020-10-07 05:39:08 後端開發

目錄
  • 1、基本介紹
  • 2、位元組碼
    • 2.1、jclasslib插件
    • 2.2、助記符
  • 3、堆疊的存盤單位--堆疊幀
    • 3.1、堆疊幀內部結構
    • 3.2、區域變數表
      • 1. 區域變數表理解
      • 2. slot理解
      • 3. slot重復利用
      • 4. 靜態變數與區域變數
      • 5. 補充說明
    • 3.3、運算元堆疊
      • 1. 運算元堆疊特點
      • 2. 運算元堆疊代碼追蹤
    • 3.4、動態鏈接
      • 1. 理解:
      • 2. 方法的呼叫
      • 3. 虛方法和非虛方法
      • 4. 方法呼叫指令
      • 5.虛方法表
    • 3.5、方法回傳地址
    • 3.6、附加資訊
  • 4、相關面試題

1、基本介紹

記憶體中的堆和堆疊:

1588419460422

1588420171154

? 注:區域變數是指8中資料型別以及物件的參考地址,

JVM直接對java堆疊的操作:

  1. 每個方法執行,伴隨著入堆疊/壓堆疊
  2. 執行結束后的出堆疊作業
  • 對于堆疊不存在垃圾回收問題

  • java堆疊的大小是動態的或者固定不變的

    • 修改堆疊大小

    1588421487510


2、位元組碼

2.1、jclasslib插件

1588567085215

1588567344617

1588567587965

2.2、助記符

  • ldc:將int,float,String型別的常量值從常量池中推送至堆疊頂(LDC類)

  • bipush:表示將單位元組(-128~127)的常量值推送至堆疊頂

  • sipush:表示將短整型常量值(-32768~32767)推送至堆疊頂(2^15=32768)

  • iconst_1:表示將int型別的1推送至堆疊頂(iconst_0~iconst_5同樣適用)

  • iconst_m1:表示將int型別的-1推送至堆疊頂(詳見ICONST類)

  • anewarray:表示創建一個參考型(類、介面)的陣列,推到堆疊頂

  • newarray:表示創建一個原始型別(int,float...)的陣列,推到堆疊頂


3、堆疊的存盤單位--堆疊幀

  1. 每個執行緒都有自己的堆疊,資料在堆疊中的存盤單位是堆疊幀
  2. 每個方法對應一個堆疊幀
  3. 堆疊幀是一個記憶體區塊,是一個資料集
  4. 執行緒之間堆疊不能共享

1588421981501

方法結束的三種方式:

  1. 正常回傳
  2. 拋出例外(未捕獲例外)結束

不管哪種方法結束,到會導致堆疊幀被彈出

? 存在呼叫關系時,當方法回傳時,當前堆疊幀會傳遞回傳結果給前一個堆疊幀,接著虛擬機拋棄當前堆疊幀,使得前一個堆疊幀未新的當前堆疊幀,

3.1、堆疊幀內部結構

3.2、區域變數表

1. 區域變數表理解

1588424390458

1588424927814

2. slot理解

1588578439201

1.引數值的存放總是在區域變數陣列的index0開始,到陣列長度-1的索引結束

2.區域變數表,最基本的存盤單元是Slot(變數槽)

3.區域變數表中存放編譯期可知的各種基本資料型別(8種),參考型別(reference),returnAddress型別的變數,

4.在區域變數表里,32位以內的型別只占用一個slot(包括returnAddress型別),64位的型別(long和double)占用兩個slot,

byte、short、char、float在存盤前被轉換為int,boolean也被轉換為int,0表示false,非0表示true;

long和double則占據兩個slot,

5.JVM會為區域變數表中的每一個slot都分配一個訪問索引,通過這個索引即可成功訪問到區域變數表中指定的區域變數值

6.當一個實體方法被呼叫的時候,它的方法引數和方法體內部定義的區域變數將會按照宣告順序被復制到區域變數表中的每一個slot上

7.如果需要訪問區域變數表中一個64bit的區域變數值時,只需要使用前一個索引即可,(比如:訪問long或者double型別變數)

8.如果當前幀是由構造方法或者實體方法創建的(意思是當前幀所對應的方法是構造器方法或者是普通的實體方法),那么該物件參考this將會存放在index為0的slot處,其余的引數按照引數表順序排列,

9.靜態方法中不能參考this,是因為靜態方法所對應的堆疊幀當中的區域變數表中不存在this

1588578990679

3. slot重復利用

堆疊幀中的區域變數表中的槽位是可以重復利用的,如果一個區域變數過了其作用域,那么在其作用域之后申明的新的區域變數就很有可能會復用過期區域變數的槽位,從而達到節省資源的目的,

1588578954421

4. 靜態變數與區域變數

變數的分類:

  • 按照資料型別分:
    • ①基本資料型別;
    • ②參考資料型別;
  • 按照在類中宣告的位置分:
    • ①成員變數:在使用前,都經歷過默認初始化賦值
      • static修飾:類變數:類加載鏈接的準備preparation階段給類變數默認賦0值——>初始化階段initialization給類變數顯式賦值即靜態代碼塊賦值;
      • 不被static修飾:實體變數:隨著物件的創建,會在堆空間分配實體變數空間,并進行默認賦值
    • ②區域變數:在使用前,必須要進行顯式賦值的!否則,編譯不通過
5. 補充說明
  • 在堆疊幀中,與性能調優關系最為密切的部分就是區域變數表,在方法執行時,虛擬機使用區域變數表完成方法的傳遞
  • 區域變數表中的變數也是重要的垃圾回收根節點,只要被區域變數表中直接或間接參考的物件都不會被回收

3.3、運算元堆疊

1.堆疊 :可以使用陣列或者鏈表來實作

2.每一個獨立的堆疊幀中除了包含區域變數表以外,還包含一個后進先出的運算元堆疊,也可以成為運算式堆疊

3.運算元堆疊,在方法執行程序中,根據位元組碼指令,往堆疊中寫入資料或提取資料,即入堆疊(push)或出堆疊(pop)

某些位元組碼指令將值壓入運算元堆疊,其余的位元組碼指令將運算元取出堆疊,使用他們后再把結果壓入堆疊,(如位元組碼指令bipush操作)

比如:執行復制、交換、求和等操作

代碼舉例

img

1. 運算元堆疊特點
  • 運算元堆疊,主要用于保存計算程序的中間結果,同時作為計算程序中變數臨時的存盤空間,
  • 運算元堆疊就是jvm執行引擎的一個作業區,當一個方法開始執行的時候,一個新的堆疊幀也會隨之被創建出來,這個方法的運算元堆疊是空的
  • 每一個運算元堆疊都會擁有一個明確的堆疊深度用于存盤數值,其所需的最大深度在編譯器就定義好了,保存在方法的code屬性中,為max_stack的值,
  • 堆疊中的任何一個元素都是可以任意的java資料型別
    • 32bit的型別占用一個堆疊單位深度
    • 64bit的型別占用兩個堆疊深度單位
  • 運算元堆疊并非采用訪問索引的方式來進行資料訪問的,而是只能通過標準的入堆疊push和出堆疊pop操作來完成一次資料訪問
  • 如果被呼叫的方法帶有回傳值的話,其回傳值將會被壓入當前堆疊幀的運算元堆疊中,并更新PC暫存器中下一條需要執行的位元組碼指令,
  • 運算元堆疊中的元素的資料型別必須與位元組碼指令的序列嚴格匹配,這由編譯器在編譯期間進行驗證,同時在類加載程序中的類驗證階段的資料流分析階段要再次驗證,
  • 另外,我們說Java虛擬機的解釋引擎是基于堆疊的執行引擎,其中的堆疊指的就是運算元堆疊,
2. 運算元堆疊代碼追蹤

結合上圖結合下面的圖來看一下一個方法(堆疊幀)的執行程序

①15入堆疊;②存盤15,15進入區域變數表

注意:區域變數表的0號位被構造器占用,這里的15從區域變數表1號開始

img

③壓入8;④8出堆疊,存盤8進入區域變數表;

img

⑤從區域變數表中把索引為1和2的是資料取出來,放到運算元堆疊;⑥iadd相加操作

img

⑦iadd操作結果23出堆疊⑧將23存盤在區域變數表索引為3的位置上istore_3

img

3.4、動態鏈接

1. 理解:

執行運行時常量池的方法參考

1、每一個堆疊幀內部都包含一個指向運行時常量池Constant pool或該堆疊幀所屬方法的參考,包含這個參考的目的就是為了支持當前方法的代碼能夠實作動態鏈接,比如invokedynamic指令

2、在Java源檔案被編譯成位元組碼檔案中時,所有的變數和方法參考都作為符號參考(symbolic Refenrence)保存在class位元組碼檔案(javap反編譯查看)的常量池里,比如:描述一個方法呼叫了另外的其他方法時,就是通過常量池中指向方法的符號參考來表示的,那么動態鏈接的作用就是為了將這些符號參考(#)最終轉換為呼叫方法的直接參考,

3、常量池的作用:提供一些符號和常量便于指令的識別,

1588731498309
2. 方法的呼叫

在JVM中,將符號參考轉換為呼叫方法的直接參考與方法的系結機制相關

  • 靜態鏈接
    當一個 位元組碼檔案被裝載進JVM內部時,如果被呼叫的目標方法在編譯期可知,且運行期保持不變時,這種情況下將呼叫方法的符號參考轉換為直接參考的程序稱之為靜態鏈接,
  • 動態鏈接
    如果被呼叫的方法在編譯期無法被確定下來,也就是說,只能夠在程式運行期將呼叫方法的符號參考轉換為直接參考,由于這種參考轉換程序具備動態性,因此也就被稱之為動態鏈接,

對應的方法的系結機制為:早起系結(Early Binding)和晚期系結(Late Bingding),系結是一個欄位、方法或者類在符號參考被替換為直接參考的程序,這僅僅發生一次,

  • 早期系結
    早期系結就是指被呼叫的目標方法如果在編譯期可知,且運行期保持不變時,即可將這個方法與所屬的型別進行系結,這樣一來,由于明確了被呼叫的目標方法究竟是哪一個,因此也就可以使用靜態鏈接的方式將符號參考轉換為直接參考,
  • 晚期系結
    如果被呼叫的方法在編譯期無法被確定下來,只能夠在程式運行期根據實際的型別系結相關的方法,這種系結方式也就被稱之為晚期系結,

隨著高級語言的橫空出世,類似于java一樣的基于面向物件的編程語言如今越來越多,盡管這類編程語言在語法風格上存在一定的差別,但是它們彼此之間始終保持著一個共性,那就是都支持封裝,集成和多型等面向物件特性,既然這一類的編程語言具備多型特性,那么自然也就具備早期系結和晚期系結兩種系結方式,
Java中任何一個普通的方法其實都具備虛函式的特征,它們相當于C++語言中的虛函式(C++中則需要使用關鍵字virtual來顯式定義),如果在Java程式中不希望某個方法擁有虛函式的特征時,則可以使用關鍵字final來標記這個方法,

3. 虛方法和非虛方法

子類物件的多型性使用前提:實際開發撰寫代碼中用的介面,實際執行是匯入的的三方jar包已經實作的功能
①類的繼承關系(父類的宣告)②方法的重寫(子類的實作)

非虛方法

  • 如果方法在編譯器就確定了具體的呼叫版本,這個版本在運行時是不可變的,這樣的方法稱為非虛方法

  • 靜態方法、私有方法、final方法、實體構造方法(實體已經確定,this()表示本類的構造器)、父類方法(super呼叫)都是非虛方法

  • 其他所有體現多型特性的方法稱為虛方法

4. 方法呼叫指令

普通呼叫指令:
1、invokestatic:呼叫靜態方法,決議階段確定唯一方法版本;
2、invokespecial:呼叫方法、私有及父類方法,決議階段確定唯一方法版本;
3、invokevirtual:呼叫所有虛方法;
4、invokeinterface:呼叫介面方法;
動態呼叫指令(Java7新增):
5、invokedynamic:動態決議出需要呼叫的方法,然后執行 .
前四條指令固化在虛擬機內部,方法的呼叫執行不可人為干預,而invokedynamic指令則支持由用戶確定方法版本,

其中invokestatic指令和invokespecial指令呼叫的方法稱為非虛方法

其中invokevirtual(final修飾的除外,JVM會把final方法呼叫也歸為invokevirtual指令,但要注意final方法呼叫不是虛方法)、invokeinterface指令呼叫的方法稱稱為虛方法,

package com.lx;

/**
 * 決議呼叫中非虛方法、虛方法的測驗
 */
class Father {
    public Father() {
        System.out.println("Father默認構造器");
    }

    public static void showStatic(String s) {
        System.out.println("Father show static" + s);
    }

    public final void showFinal() {
        System.out.println("Father show final");
    }

    public void showCommon() {
        System.out.println("Father show common");
    }

}

public class Son extends Father {
    public Son() {
        //invokespecial--->父類構造方法
        super();
    }

    public Son(int age) {
        this();
    }

    public static void main(String[] args) {
       //invokespecial-->構造方法
        Son son = new Son();
        //invokevirtual--->其它方法
        son.show();
    }

    //不是重寫的父類方法,因為靜態方法不能被重寫
    public static void showStatic(String s) {
        System.out.println("Son show static" + s);
    }

    private void showPrivate(String s) {
        System.out.println("Son show private" + s);
    }

    public void show() {
        //invokestatic--->靜態方法
        showStatic(" 兒子");

        //invokespecial--->私有方法
        showPrivate(" hello!");

        /*invokevirtual --->final方法
            因為此方法宣告有final 不能被子類重寫,所以也認為該方法是非虛方法
            JVM會把final方法呼叫也歸為invokevirtual指令*/
        showFinal();
        //invokespecial---->父類方法
        super.showFinal();
        //invokespecial--->父類方法
        super.showCommon();

        /*虛方法如下*/

        //invokevirtual
        showCommon();//沒有顯式加super,被認為是虛方法,因為無法去頂子類是否重寫了showCommon
        info();

        MethodInterface in = null;
        //invokeinterface  不確定介面實作類是哪一個 需要重寫
        in.methodA();

    }

    public void info() {

    }

}

interface MethodInterface {
    void methodA();
}
5.虛方法表
  • 在面向物件編程中,會很頻繁期使用到動態分派,如果在每次動態分派的程序中都要重新在累的方法元資料中搜索合適的目標的話就可能影響到執行效率,因此,為了提高性能,jvm采用在類的方法區建立一個虛方法表(virtual method table)(非虛方法不會出現在表中)來實作,使用索引表來代替查找,

  • 每個類中都有一個虛方法表,表中存放著各個方法的實際入口,

  • 虛方法表什么時候被創建?

虛方法表會在類加載的鏈接階段被創建 并開始初始化,類的變數初始值準備完成之后,jvm會把該類的虛方法表也初始化完畢,

1588820717280

3.5、方法回傳地址

  • 存放呼叫該方法的PC暫存器的值,
  • 一個方法的結束,有兩種方式:
    • 正常執行完成
    • 出現未處理的例外,非正常退出
  • 無論通過哪種方式退出,在方法退出后都回傳到該方法被呼叫的位置,方法正常退出時,呼叫者(方法的呼叫者可能也是一個方法)的pc計數器的值作為回傳地址,即呼叫該方法的指令的下一條指令的地址,而通過例外退出時,回傳地址是要通過例外表來確定,堆疊幀中一般不會保存這部分資訊,
  • 本質上,方法的退出就是當前堆疊幀出堆疊的程序,此時,需要恢復上層方法的區域變數表、運算元堆疊、將回傳值入呼叫者堆疊幀的運算元堆疊、設定PC暫存器值等,讓呼叫者方法繼續執行下去,
  • 正常完成出口和例外完成出口的區別在于:通過例外完成出口退出的不會給他的上層呼叫者產生任何的回傳值,

當一個方法開始執行后,只有兩種方式可以退出這個方法

1、執行引擎遇到任意一個方法回傳的位元組碼指令(return),會有回傳值傳遞給上層的方法呼叫者,簡稱正常完成出口;

  • 一個方法在正常呼叫完成之后究竟需要使用哪一個回傳指令還需要根據方法回傳值的實際資料型別而定
  • 在位元組碼指令中,回傳指令包含ireturn(當回傳值是boolena、byte、char、short和int型別時使用)、lreturn、freturn、dreturn以及areturn(參考型別的)
  • 另外還有一個return指令供宣告為void的方法、實體初始化方法、類和介面的初始化方法使用

2、在方法執行的程序中遇到了例外(Exception),并且這個例外沒有在方法內進行處理,也就是只要在本方法的例外表中沒有搜素到匹配的例外處理器,就會導致方法退出,簡稱例外完成出口

  • 方法執行程序中拋出例外時的例外處理,存盤在一個例外處理表,方便在發生例外的時候找到處理例外的代碼,

    1588822291355

1588822402425

3.6、附加資訊

堆疊幀中還允許攜帶與java虛擬機實作相關的一些附加資訊,例如,對程式除錯提供支持的資訊,(很多資料都忽略了附加資訊)


4、相關面試題

1588823434132

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/160764.html

標籤:Java

上一篇:一張圖搞懂Spring bean的完整生命周期

下一篇:JVM--堆

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more