欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

解讀Java報錯輸出的信息究竟是什么

 更新時間:2024年12月25日 16:00:47   作者:高錳酸鉀_  
Java報錯輸出的信息主要包括異常的主要描述信息和當前線程的棧幀信息,棧幀是虛擬機棧的基本存儲單元,主要由局部變量表、操作數(shù)棧和幀數(shù)據(jù)三部分組成,局部變量表用于存放方法的參數(shù)和局部變量,操作數(shù)棧用于保存計算過程中產(chǎn)生的中間結(jié)果

Java報錯輸出的信息究竟是什么?

本篇會帶大家了解一下java運行時報錯輸出的信息內(nèi)容,簡單學習一下虛擬機內(nèi)存中Java虛擬機棧的工作方式以及棧幀中所存儲的信息內(nèi)容

異常信息

當你的程序運行報錯時,你是否會好奇打印出來的那一大坨紅色的究竟是什么?

首先,報錯的第一行是異常的主要描述信息,那么剩下的基本都是當前線程的棧幀信息

比如上圖對于異常的描述是

Access denied for user 'root'@'localhost' (using password: YES)

我們的數(shù)據(jù)庫訪問被拒絕了,原因就是我把密碼輸入錯誤了

那么異常描述下面的信息就是棧幀信息了

什么是棧幀呢,棧幀中又包含了哪些信息?

虛擬機棧

在我們的Java虛擬機中,有一個組成部分叫做運行時數(shù)據(jù)區(qū),它是程序執(zhí)行過程中用于存儲數(shù)據(jù)的內(nèi)存區(qū)域,這個區(qū)域用于存儲程序運行過程中的各種數(shù)據(jù),包括對象實例、類信息、局部變量、方法調(diào)用信息等

在運行時數(shù)據(jù)區(qū)中,又有一部分是虛擬機棧,每個線程都有一個獨立的虛擬機棧,當方法被調(diào)用時,會在棧中創(chuàng)建一個新的棧幀(Stack Frame),當方法執(zhí)行完畢后,棧幀會被彈出,控制權(quán)回到調(diào)用方,所以虛擬機棧中進進出出的就是程序中的方法的棧幀

那么虛擬機棧是怎么運行的呢

這里以一段代碼的運行為例子:

public class Stark {
    public static void main(String[] args) {
        FunctionA();
    }
    public static void FunctionA(){
        System.out.println("運行了A");
        FunctionB();
    }
    public static void FunctionB(){
        System.out.println("運行了B");
    }
}

當我們運行這段程序時,第一個執(zhí)行的是Main方法,在Main方法中又調(diào)用執(zhí)行了A方法,在A方法中又執(zhí)行了B方法,那么在虛擬機棧中,要執(zhí)行的方法的棧幀會進入虛擬機棧中,待方法完全執(zhí)行完畢后,他的棧幀才會被彈出:

此時,三個方法都還沒有完全結(jié)束,當B方法被調(diào)用,輸出"運行了B"后,B方法的棧幀才會彈出虛擬機棧,以此類推:

這就是虛擬機棧的運行過程,我們也可以在IDEA中使用斷點調(diào)試查看到線程的虛擬機棧,依然使用上面的代碼,在B方法上打斷點,點擊調(diào)試運行:

在左下角就可以看到目前存在的線程中的棧中有哪些棧幀:

此時正處于B方法中,也就是上圖中A方法剛剛調(diào)用的B方法,B方法還未結(jié)束時,棧中有三個方法的棧幀信息

文章開頭提到,報錯時會輸出當前線程全部的棧幀信息,我們可以試一下

在上述代碼的B方法中添加一句拋出異常的代碼:

public class Stark {
    public static void main(String[] args) {
        FunctionA();
    }
    public static void FunctionA(){
        System.out.println("運行了A");
        FunctionB();
    }
    public static void FunctionB(){
        System.out.println("運行了B");
        throw new RuntimeException("出錯");
    }
}

執(zhí)行代碼,你可以在控制臺看到打印出了如下內(nèi)容:

在報錯信息的第一行顯示,我們在線程mian中發(fā)生了運行時異常,異常信息:“出錯”

接著,很顯然下面的部分就是棧幀信息,他的打印順序就是當前虛擬機棧中的全部棧幀依次打印

什么是棧幀

相信看到這里,你會發(fā)出疑問,什么是棧幀呢?虛擬機棧中放入的棧幀到底是個什么東西呢?

棧幀是虛擬機棧的基本存儲單元,主要是由三部分組成:

  • 局部變量表:
    用于存放方法的參數(shù)和局部變量。這些變量在方法執(zhí)行過程中會被頻繁訪問,因此將它們存儲在棧幀中可以提高訪問速度。局部變量表中的變量在方法調(diào)用時初始化,并在方法執(zhí)行完畢后銷毀
  • 操作數(shù)棧:
    用于保存計算過程中產(chǎn)生的中間結(jié)果和作為計算單元的操作數(shù)。操作數(shù)棧是一個后進先出(LIFO)的數(shù)據(jù)結(jié)構(gòu),與局部變量表一起支持方法的執(zhí)行。
  • 幀數(shù)據(jù):
    主要包含動態(tài)鏈接、方法出口、異常表等信息

局部變量表

我們編譯StarkTest類并查看他的字節(jié)碼文件:

public class StarkTest {
    public static void main(String[] args) {
        int i = 0;
        int j = i + 1;
    }
}

打開方法,找到Mian方法下的LocalVariableTable就是局部變量表,表中會把方法中的參數(shù)和局部變量存放起來,索引從0開始,由于我們的main方法傳入了參數(shù)args,那么表中下標為0的槽中放了args,方法中我們又聲明了i,和j,那么他們會依次保存到槽中

其實局部變量表就是一個數(shù)組,每一個位置被稱為一個槽,除了long類型和double類型的變量要占兩個槽,其余的都只占一個槽,需要注意的是如果該方法不是靜態(tài)方法而是示例方法,該方法運行時局部變量表的第一個槽會存放調(diào)用該方法的實例對象,也就是this

局部變量表中存放的變量如果在其生效范圍內(nèi)不會在被使用,那么之后的變量或是參數(shù)就可以覆蓋他的槽,以此節(jié)省空間

操作數(shù)棧

他就是一塊用來存放運行時中間數(shù)據(jù)的區(qū)域,比如上邊代碼中int i = 0;int j = i + 1;這兩行代碼執(zhí)行的過程,先把0放入操作數(shù)棧中,再將操作數(shù)棧中的數(shù)賦值給變量i,然后把i的值放入操作數(shù)棧中,再把1也放入操作數(shù)棧中,讓操作數(shù)棧中的兩個數(shù)相加,再賦值給變量j:

幀數(shù)據(jù)

幀數(shù)據(jù)中主要是動態(tài)鏈接,方法出口

  • 動態(tài)鏈接:
    用于維護方法調(diào)用時的符號引用轉(zhuǎn)化為直接引用的信息。在Java中,每個類都有一個常量池,用于存儲符號引用。當方法被調(diào)用時,JVM會通過動態(tài)鏈接將符號引用轉(zhuǎn)化為直接引用,以便在方法執(zhí)行過程中訪問其他類或方法。
  • 方法出口:
    記錄方法正常退出或異常退出時的處理信息。當方法執(zhí)行完畢后,JVM會根據(jù)方法出口的信息將控制權(quán)返回給調(diào)用者。如果方法在執(zhí)行過程中拋出異常,JVM也會根據(jù)方法出口的信息來處理異常

總結(jié)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java?Spring?Boot請求方式與請求映射過程分析

    Java?Spring?Boot請求方式與請求映射過程分析

    這篇文章主要介紹了Java?Spring?Boot請求方式與請求映射過程分析,Spring?Boot支持Rest風格:使用HTTP請求方式的動詞來表示對資源的操作
    2022-06-06
  • 使用JVMTI實現(xiàn)SpringBoot的jar加密,防止反編譯

    使用JVMTI實現(xiàn)SpringBoot的jar加密,防止反編譯

    這篇文章主要介紹了使用JVMTI實現(xiàn)SpringBoot的jar加密,防止反編譯問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-08-08
  • 詳解Java如何優(yōu)雅的實現(xiàn)字典翻譯

    詳解Java如何優(yōu)雅的實現(xiàn)字典翻譯

    當我們在Java應用程序中需要對字典屬性進行轉(zhuǎn)換返回給前端時,如何簡單、方便、并且優(yōu)雅的處理是一個重要問題。在本文中,我們將介紹如何使用Java中的序列化機制來優(yōu)雅地實現(xiàn)字典值的翻譯,從而簡化開發(fā)
    2023-04-04
  • Spring MVC學習教程之RequestMappingHandlerAdapter詳解

    Spring MVC學習教程之RequestMappingHandlerAdapter詳解

    這篇文章主要給大家介紹了關(guān)于Spring MVC學習教程之RequestMappingHandlerAdapter的相關(guān)資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考借鑒,下面隨著小編來一起學習學習吧
    2018-11-11
  • SpringBoot之Refresh流程的簡單說明

    SpringBoot之Refresh流程的簡單說明

    這篇文章主要介紹了SpringBoot之Refresh流程的簡單說明,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • 基于多線程并發(fā)的常見問題(詳解)

    基于多線程并發(fā)的常見問題(詳解)

    下面小編就為大家?guī)硪黄诙嗑€程并發(fā)的常見問題(詳解)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-10-10
  • Spring AOP注解案例及基本原理詳解

    Spring AOP注解案例及基本原理詳解

    這篇文章主要介紹了Spring AOP注解案例及基本原理詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-06-06
  • Spring-boot原理及spring-boot-starter實例和代碼

    Spring-boot原理及spring-boot-starter實例和代碼

    spring-boot的starter是一個通過maven完成自包含并通過annotation配置使得可被spring上下文發(fā)現(xiàn)并實例化的一個可插拔的組件或服務。這篇文章主要介紹了Spring-boot原理及spring-boot-starter實例和代碼 ,需要的朋友可以參考下
    2019-06-06
  • 詳解pom如何引入非Maven工程的jar包

    詳解pom如何引入非Maven工程的jar包

    系統(tǒng)遷移從某個公有云遷移到私有云,因為現(xiàn)在國內(nèi)大力推行國產(chǎn)化,所以我們這次遷移有兩個國產(chǎn)化的東西,第一個是操作系統(tǒng)采用了歐拉操作系統(tǒng),第二個就是數(shù)據(jù)庫采用了goldendb,本文給大家詳細介紹了pom如何引入非Maven工程的jar包,需要的朋友可以參考下
    2023-12-12
  • Mybatis入門教程(四)之mybatis動態(tài)sql

    Mybatis入門教程(四)之mybatis動態(tài)sql

    這篇文章主要介紹了Mybatis入門教程(四)之mybatis動態(tài)sql的相關(guān)資料,涉及到動態(tài)sql及動態(tài)sql的作用知識,本文介紹的非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2016-09-09

最新評論