中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當前位置: 首頁 > news >正文

做建筑設計網站怎么建立網站平臺

做建筑設計網站,怎么建立網站平臺,廣州市住房和城鄉(xiāng)建設委員會網站6,建設h5網站文章目錄 前言1. if語句字節(jié)碼的解析 2. for循環(huán)字節(jié)碼的解析 3. while循環(huán)4. switch語句5. try-catch語句6. i 和i的字節(jié)碼7. try-catch-finally8. 參考文檔 前言 上一章我們聊了《JVM字節(jié)碼指令詳解》 。本章我們學以致用,聊一下我們常見的一些java語句的特性底層…

文章目錄

  • 前言
  • 1. if語句
    • 字節(jié)碼的解析
  • 2. for循環(huán)
    • 字節(jié)碼的解析
  • 3. while循環(huán)
  • 4. switch語句
  • 5. try-catch語句
  • 6. i++ 和++i的字節(jié)碼
  • 7. try-catch-finally
  • 8. 參考文檔

前言

上一章我們聊了《JVM字節(jié)碼指令詳解》 。本章我們學以致用,聊一下我們常見的一些java語句的特性底層是如何實現。
在這里插入圖片描述

1. if語句

if語句是我們最常用的判斷語句之一,它的底層實現原理是什么呢?可以通過反編譯字節(jié)碼來分析一下。

假設我們有以下的java代碼:

public class IfStatement {public static void main(String[] args) {int a = 10;if (a > 0) {System.out.println("a is positive");} else {System.out.println("a is negative or zero");}}
}

可以使用javap命令來反編譯字節(jié)碼:

javap -c IfStatement.class

輸出結果如下:

public class IfStatement {// 構造方法public IfStatement();Code:0: aload_0                     // 將局部變量表中的第0個元素(通常是this引用)入棧1: invokespecial #1            // 調用父類Object的構造方法4: return                      // 方法返回// main方法public static void main(java.lang.String[]);Code:0: bipush        10            // 將10壓入棧頂2: istore_1                    // 將棧頂元素(10)存入局部變量表的第1個位置3: iload_1                     // 將局部變量表的第1個位置的元素(10)入棧4: ifle          17            // 判斷棧頂元素(10)是否小于等于0,如果是則跳轉到指令177: getstatic     #2            // 獲取System類的out字段,類型是PrintStream10: ldc           #3            // 將字符串"a is positive"壓入棧頂12: invokevirtual #4            // 調用PrintStream的println方法輸出字符串15: goto          23            // 無條件跳轉到指令2318: getstatic     #2            // 獲取System類的out字段,類型是PrintStream21: invokevirtual #5            // 調用PrintStream的println方法輸出局部變量表第1個位置的元素(10)24: return                      // 方法返回
}

字節(jié)碼的解析

  • 在main方法中,首先將10壓入棧頂,然后將其存入局部變量表的第1個位置。然后將局部變量表的第1個位置的元素(10)入棧,判斷其是否小于等于0,如果是則跳轉到指令17,否則執(zhí)行下一條指令。在指令7-15中,它獲取System的out字段,將字符串"a is positive"壓入棧頂,然后調用println方法輸出這個字符串,最后無條件跳轉到指令23。在指令18-21中,它獲取System的out字段,然后調用println方法輸出局部變量表第1個位置的元素(10)。最后,main方法返回。

2. for循環(huán)

for循環(huán)是我們常用的循環(huán)語句之一,它的底層實現原理是什么呢?我們還是可以通過反編譯字節(jié)碼來分析一下。

假設我們有以下的java代碼:

public class ForLoop {public static void main(String[] args) {for (int i = 0; i < 10; i++) {System.out.println("i = " + i);}}
}

可以使用javap命令來反編譯字節(jié)碼:

javap -c ForLoop.class

這是一個包含for循環(huán)的Java類ForLoop的字節(jié)碼輸出,下面是中文注釋:

public class ForLoop {// 構造方法public ForLoop();Code:0: aload_0                     // 將局部變量表中的第0個元素(通常是this引用)入棧1: invokespecial #1            // 調用父類Object的構造方法4: return                      // 方法返回// main方法public static void main(java.lang.String[]);Code:0: iconst_0                    // 將0壓入棧頂1: istore_1                    // 將棧頂元素(0)存入局部變量表的第1個位置2: iload_1                     // 將局部變量表的第1個位置的元素(0)入棧3: bipush        10            // 將10壓入棧頂5: if_icmpge     19            // 如果局部變量表的第1個位置的元素(0)大于等于棧頂元素(10),則跳轉到指令198: getstatic     #2            // 獲取System類的out字段,類型是PrintStream11: new           #3            // 創(chuàng)建一個StringBuilder類的對象14: dup                         // 復制棧頂元素,此時棧頂有兩個相同的StringBuilder對象引用15: invokespecial #4            // 調用StringBuilder類的構造函數初始化對象18: ldc           #5            // 將字符串"i ="壓入棧頂20: invokevirtual #6            // 調用StringBuilder的append方法將字符串添加到StringBuilder23: iload_1                     // 將局部變量表的第1個位置的元素(0)入棧24: invokevirtual #7            // 調用StringBuilder的append方法將數字添加到StringBuilder27: invokevirtual #8            // 調用StringBuilder的toString方法將StringBuilder轉化為字符串30: invokevirtual #9            // 調用PrintStream的println方法輸出字符串33: iinc          1, 1          // 將局部變量表的第1個位置的元素(0)增加136: goto          2             // 無條件跳轉到指令2,形成循環(huán)39: return                      // 方法返回LineNumberTable:line 3: 0line 4: 8line 3: 33line 6: 39StackMapTable: number_of_entries = 2frame_type = 252 /* append */offset_delta = 2locals = [ int, int ]stack = []frame_type = 250 /* chop */offset_delta = 36
}

字節(jié)碼的解析

可以看到,for循環(huán)的底層實現是通過if_icmpge指令來實現的。在本例中,當i小于10時,會執(zhí)行第8行的輸出語句;否則,會跳轉到第39行,結束循環(huán)。

  • 在main方法中,首先將0壓入棧頂,然后將其存入局部變量表的第1個位置。接下來是一個循環(huán),循環(huán)條件是局部變量表的第1個位置的元素小于10。在循環(huán)體中,它首先獲取System的out字段,然后創(chuàng)建一個StringBuilder對象并初始化,然后將字符串"i ="和局部變量表的第1個位置的元素添加到StringBuilder,然后將StringBuilder轉化為字符串,然后調用println方法輸出字符串。在循環(huán)體結束時,它將局部變量表的第1個位置的元素加1,然后無條件跳轉到指令2,形成循環(huán)。當循環(huán)結束時,main方法返回。

3. while循環(huán)

while循環(huán)是我們常用的循環(huán)語句之一,它的底層實現原理是什么呢?我們還是可以通過反編譯字節(jié)碼來分析一下。

假設我們有以下的java代碼:

public class WhileLoop {public static void main(String[] args) {int i = 0;while (i < 10) {System.out.println("i = " + i);i++;}}
}

可以使用javap命令來反編譯字節(jié)碼:

javap -c WhileLoop.class

輸出結果如下:

public class WhileLoop {public WhileLoop();Code:0: aload_01: invokespecial #1                  // Method java/lang/Object."<init>":()V4: returnpublic static void main(java.lang.String[]);Code:0: iconst_01: istore_12: iload_13: bipush        105: if_icmpge     198: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;11: new           #3                  // class java/lang/StringBuilder14: dup15: invokespecial #4                  // Method java/lang/StringBuilder."<init>":()V18: ldc           #5                  // String i =20: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;23: iload_124: invokevirtual #7                  // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;27: invokevirtual #8                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;30: invokevirtual #9                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V33: iinc          1, 136: goto          239: returnLineNumberTable:line 3: 0line 4: 2line 5: 8line 6: 33line 5: 36line 8: 39StackMapTable: number_of_entries = 2frame_type = 252 /* append */offset_delta = 2locals = [ int, int ]stack = []frame_type = 250 /* chop */offset_delta = 36
}

可以看到,while循環(huán)的底層實現也是通過if_icmpge指令來實現的。在本例中,當i小于10時,會執(zhí)行第8行的輸出語句;否則,會跳轉到第39行,結束循環(huán)。

4. switch語句

switch語句是我們常用的分支語句之一,它的底層實現原理是什么呢?我們還是可以通過反編譯字節(jié)碼來分析一下。

假設我們有以下的java代碼:

public class SwitchStatement {public static void main(String[] args) {int i = 2;switch (i) {case 1:System.out.println("i is 1");break;case 2:System.out.println("i is 2");break;case 3:System.out.println("i is 3");break;default:System.out.println("i is neither 1, 2 nor 3");break;}}
}

可以使用javap命令來反編譯字節(jié)碼:

javap -c SwitchStatement.class

輸出結果如下:

public class SwitchStatement {public SwitchStatement();Code:0: aload_01: invokespecial #1                  // Method java/lang/Object."<init>":()V4: returnpublic static void main(java.lang.String[]);Code:0: iconst_21: istore_12: iload_13: tableswitch   { // 1 to 31: 282: 403: 52default: 64}28: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;31: ldc           #3                  // String i is 133: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V36: goto          7140: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;43: ldc           #5                  // String i is 245: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V48: goto          7152: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;55: ldc           #6                  // String i is 357: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V60: goto          7164: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;67: invokevirtual #7                  // Method java/io/PrintStream.println:()V70: return71: returnLineNumberTable:line 3: 0line 4: 2line 5: 28line 6: 40line 7: 52line 8: 64line 9: 70line 7: 71StackMapTable: number_of_entries = 5frame_type = 252 /* append */offset_delta = 28locals = [ int ]frame_type = 252 /* append */offset_delta = 11locals = [ int ]frame_type = 252 /* append */offset_delta = 12locals = [ int ]frame_type = 252 /* append */offset_delta = 12locals = [ int ]frame_type = 252 /* append */offset_delta = 3locals = [ int ]

可以看到,switch語句的底層實現是通過tableswitch指令來實現的。在本例中,當i等于1時,會執(zhí)行第28行的輸出語句;當i等于2時,會執(zhí)行第40行的輸出語句;當i等于3時,會執(zhí)行第52行的輸出語句;否則,會執(zhí)行第64行的輸出語句。

5. try-catch語句

try-catch語句是我們常用的異常處理語句之一,它的底層實現原理是什么呢?我們還是可以通過反編譯字節(jié)碼來分析一下。

假設我們有以下的java代碼:

public class TryCatchStatement {public static void main(String[] args) {try {int[] arr = new int[3];arr[4] = 5;} catch (ArrayIndexOutOfBoundsException e) {System.out.println("Array index out of bounds!");}}
}

可以使用javap命令來反編譯字節(jié)碼:

javap -c TryCatchStatement.class

輸出結果如下:

public class TryCatchStatement {public TryCatchStatement();Code:0: aload_01: invokespecial #1                  // Method java/lang/Object."<init>":()V4: returnpublic static void main(java.lang.String[]);Code:0: iconst_01: newarray       int3: astore_14: aload_15: iconst_46: iconst_57: iastore8: goto          1911: astore_112: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;15: ldc           #3                  // String Array index out of bounds!17: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V20: returnException table:from    to  target type0     8    11   Class java/lang/ArrayIndexOutOfBoundsExceptionLineNumberTable:line 3: 0line 4: 4line 5: 11line 6: 12line 7: 20StackMapTable: number_of_entries = 2frame_type = 34 /* same */frame_type = 1 /* same_locals_1_stack_item */stack = [ class java/lang/ArrayIndexOutOfBoundsException ]
}

可以看到,try-catch語句的底層實現是通過異常表來實現的。在本例中,當數組下標越界時,會執(zhí)行第12行的輸出語句;否則,會跳轉到第20行,繼續(xù)執(zhí)行。

6. i++ 和++i的字節(jié)碼

i++++i 在語義上有些許不同,在字節(jié)碼層面也有所體現。下面是它們的字節(jié)碼層面的解釋:

假設 i 是局部變量表的索引為1的變量。

i++ 的偽字節(jié)碼:

iload_1                 // 從局部變量表中加載變量 i 到操作數棧頂
iinc 1 by 1             // 將局部變量表中的變量 i 增加1

++i 的偽字節(jié)碼:

iinc 1 by 1             // 將局部變量表中的變量 i 增加1
iload_1                 // 從局部變量表中加載變量 i 到操作數棧頂

可以看到,i++++i 的主要區(qū)別在于加載和增加操作的順序不同。i++ 是先將 i 加載到操作數棧頂,然后再增加 i 的值;而 ++i 是先增加 i 的值,然后再將 i 加載到操作數棧頂。這就解釋了 i++++i 在語義上的不同:i++ 是先取值后加1,++i 是先加1后取值。

7. try-catch-finally

在 Java 字節(jié)碼中,try-catch-finally 結構主要通過異常表(Exception Table)來實現。Java 字節(jié)碼并沒有專門的指令來表示 try、catch 或者 finally 塊。相反,它通過在異常表中記錄 try 塊的開始和結束位置、catch 塊的開始位置和要捕獲的異常類型,以實現異常處理的流程。

下面是一個簡單的 try-catch-finally 代碼例子:

void test() {try {System.out.println("try block");throw new Exception();} catch (Exception e) {System.out.println("catch block");} finally {System.out.println("finally block");}
}

對應的字節(jié)碼指令

0: getstatic     #2   // 獲取 java/lang/System 類的 out 字段,是 PrintStream 類型
3: ldc           #3   // 將常量池中的 "try block" 字符串壓入棧頂
5: invokevirtual #4   // 調用 PrintStream 類的 println 方法輸出字符串
8: new           #5   // 創(chuàng)建一個 java/lang/Exception 類的對象
11: dup           // 復制棧頂的元素,此時棧頂有兩個相同的異常對象引用
12: invokespecial #6   // 調用 Exception 類的構造函數初始化對象
15: athrow         // 拋出棧頂的異常對象
16: astore_1       // 捕獲異常并存入局部變量表的第1個位置
17: getstatic     #2   // 獲取 java/lang/System 類的 out 字段,是 PrintStream 類型
20: ldc           #7   // 將常量池中的 "catch block" 字符串壓入棧頂
22: invokevirtual #4   // 調用 PrintStream 類的 println 方法輸出字符串
25: jsr           26   // 無條件跳轉到指令26(finally塊的起始位置)
28: goto          34   // 執(zhí)行完finally塊后,跳過 catch 塊剩下的代碼,進入下一個處理流程
31: astore_2       // 捕獲從finally塊拋出的異常并存入局部變量表的第2個位置
32: jsr           26   // 無條件跳轉到指令26(finally塊的起始位置)
35: aload_2        // 從局部變量表的第2個位置加載異常對象至棧頂
36: athrow         // 再次拋出該異常對象
37: astore_3       // 捕獲異常并存入局部變量表的第3個位置
38: getstatic     #2   // 獲取 java/lang/System 類的 out 字段,是 PrintStream 類型
41: ldc           #8   // 將常量池中的 "finally block" 字符串壓入棧頂
43: invokevirtual #4   // 調用 PrintStream 類的 println 方法輸出字符串
46: ret           3    // 返回到 astore_3 指令之后的代碼

這段字節(jié)碼中使用了 jsrret 指令,這兩個指令主要用于實現 finally 塊的邏輯。jsr 指令會跳轉到 finally 塊的代碼,然后 ret 指令用于返回到 finally 塊之前的代碼繼續(xù)執(zhí)行。

字節(jié)碼的解釋

  • 行0-15:這部分對應 try 塊的內容。在這個例子中,它首先通過 getstatic 指令獲取 System.out 對象,然后通過 ldc 指令加載常量 “try block”,最后調用 println 方法輸出這個字符串。然后,它創(chuàng)建一個 Exception 對象并拋出。

  • 行16-25:這部分對應 catch 塊的內容。當 try 塊拋出異常時,執(zhí)行流程會跳轉到這部分。在這個例子中,它首先通過 astore 指令將異常對象存儲到局部變量表,然后類似于 try 塊的處理,輸出 “catch block” 字符串。

  • 行37-46:這部分對應 finally 塊的內容。無論 try 塊是否拋出異常,這部分代碼總是會被執(zhí)行。在這個例子中,它輸出 “finally block” 字符串。

  • 行25-32和行35-36:這部分是對異常處理的一些額外控制。jsr 和 ret 指令用于實現無條件的跳轉,確保 finally 塊總是會被執(zhí)行。

8. 參考文檔

  1. 張亞 《深入理解JVM字節(jié)碼》
  2. https://www.jonesjalapat.com/2021/09/11/internal-working-of-java-virtual-machine/
http://www.risenshineclean.com/news/27547.html

相關文章:

  • 坊網站建設seo快速排名工具
  • ps怎么排版規(guī)劃設計網站國外網站推廣平臺有哪些?
  • 在線咨詢網站模板做app推廣去哪找商家
  • 網站建設模板網站排名優(yōu)化快速
  • 自建個人網站怎么自己創(chuàng)建一個網頁
  • wordpress 游戲模版seo輿情優(yōu)化
  • crm管理seo培訓一對一
  • 做網站應注意什么新網域名注冊查詢
  • 寶安商城網站建設哪家便宜百度搜索引擎平臺
  • 興化網站建設推廣軟文發(fā)布平臺
  • 做任務得傭金的網站seo綜合查詢中的具體內容有哪些
  • 怎么做免費的網站推廣高級seo
  • oa軟件開發(fā)定制seo求職
  • 網站文字設計搜索引擎營銷sem包括
  • 一個公司多個網站做優(yōu)化今天新聞頭條
  • 網站建設與維護作業(yè)東莞seo計費管理
  • 網站建設推廣怎么做百度旗下產品
  • 建設網站后怎么發(fā)布長沙網絡推廣公司
  • 網站打開的速度慢網絡營銷的工具和方法有哪些
  • wordpress儀表盤文件目錄seo挖關鍵詞
  • 微信小程序怎么做購物網站推廣普通話的宣傳內容
  • 創(chuàng)業(yè) 做網站培訓心得簡短200字
  • 邱縣網站建設今日國內新聞大事20條
  • 四川省建設資格注冊中心網站重慶seo公司怎么樣
  • 龍巖做網站多少錢競價網絡推廣外包
  • 網站制作那家便宜網絡營銷有哪些推廣方式
  • 營銷微網站建設公司seo推廣方案怎么做
  • 網站顯示內容不顯示企業(yè)營銷推廣怎么做
  • 貴陽模板建站定制做seo必須有網站嗎
  • 隨州做網站的公司全網關鍵詞云怎么查