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

解讀Java報(bào)錯(cuò)輸出的信息究竟是什么

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

Java報(bào)錯(cuò)輸出的信息究竟是什么?

本篇會(huì)帶大家了解一下java運(yùn)行時(shí)報(bào)錯(cuò)輸出的信息內(nèi)容,簡(jiǎn)單學(xué)習(xí)一下虛擬機(jī)內(nèi)存中Java虛擬機(jī)棧的工作方式以及棧幀中所存儲(chǔ)的信息內(nèi)容

異常信息

當(dāng)你的程序運(yùn)行報(bào)錯(cuò)時(shí),你是否會(huì)好奇打印出來(lái)的那一大坨紅色的究竟是什么?

首先,報(bào)錯(cuò)的第一行是異常的主要描述信息,那么剩下的基本都是當(dāng)前線程的棧幀信息

比如上圖對(duì)于異常的描述是

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

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

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

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

虛擬機(jī)棧

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

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

那么虛擬機(jī)棧是怎么運(yùn)行的呢

這里以一段代碼的運(yùn)行為例子:

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

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

此時(shí),三個(gè)方法都還沒(méi)有完全結(jié)束,當(dāng)B方法被調(diào)用,輸出"運(yùn)行了B"后,B方法的棧幀才會(huì)彈出虛擬機(jī)棧,以此類推:

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

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

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

文章開頭提到,報(bào)錯(cuò)時(shí)會(huì)輸出當(dāng)前線程全部的棧幀信息,我們可以試一下

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

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

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

在報(bào)錯(cuò)信息的第一行顯示,我們?cè)诰€程mian中發(fā)生了運(yùn)行時(shí)異常,異常信息:“出錯(cuò)”

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

什么是棧幀

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

棧幀是虛擬機(jī)棧的基本存儲(chǔ)單元,主要是由三部分組成:

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

局部變量表

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

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

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

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

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

操作數(shù)棧

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

幀數(shù)據(jù)

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

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

總結(jié)

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

相關(guān)文章

  • Java?Spring?Boot請(qǐng)求方式與請(qǐng)求映射過(guò)程分析

    Java?Spring?Boot請(qǐng)求方式與請(qǐng)求映射過(guò)程分析

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

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

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

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

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

    Spring MVC學(xué)習(xí)教程之RequestMappingHandlerAdapter詳解

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

    SpringBoot之Refresh流程的簡(jiǎn)單說(shuō)明

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

    基于多線程并發(fā)的常見(jiàn)問(wèn)題(詳解)

    下面小編就為大家?guī)?lái)一篇基于多線程并發(fā)的常見(jiàn)問(wèn)題(詳解)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-10-10
  • Spring AOP注解案例及基本原理詳解

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

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

    Spring-boot原理及spring-boot-starter實(shí)例和代碼

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

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

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

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

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

最新評(píng)論