在IDEA利用斷點(diǎn)debug+解析class文件+jclasslib插件

目錄
1、在IDEA利用斷點(diǎn)進(jìn)行debug模式,觀察棧幀的入棧出棧
2、在IDEA中使用javap指令對(duì)class文件進(jìn)行解析
3、在IDEA中利用jclasslib插件解析.class文件

在IDEA中輸入這樣的代碼

import java.util.function.DoubleToIntFunction;
/*
(1)現(xiàn)在設(shè)置的代碼補(bǔ)全是alt+/
(2)快速注釋是command+/
(3)快速格式化代碼 alt+command+L
(4)利用斷點(diǎn)進(jìn)入debug模式,觀察棧的棧幀和局部變量表,進(jìn)棧出棧操作

進(jìn)入都o(jì)ut/production/learnJVMdemo文件夾下,有一個(gè)當(dāng)前類的.class文件,對(duì)它進(jìn)行反編譯
在Terminal界面下輸入反編譯指令:javap -v StackFrameTest.class,觀察反編譯的輸出結(jié)果
*/
public class TestStackFrame {

    public static void main(String[] args) {

        System.out.println("這是main即將執(zhí)行");
        TestStackFrame tt = new TestStackFrame();
        try {
            tt.method1();
        }catch (Exception e){
            e.printStackTrace();
        }
        tt.method1();
        System.out.println();
        System.out.println("這是main執(zhí)行完畢");
    }

    public  void method1(){
        System.out.println("這是method1即將執(zhí)行");
        int I=10;
        int j=11;
        method2();
        //System.out.println(10/0); //這個(gè)會(huì)報(bào)出一個(gè)錯(cuò)誤

        System.out.println("這是method1執(zhí)行完畢");
    }
    public void method2(){
        System.out.println("這是method2即將執(zhí)行");
        int I=10;
        int j=11;
        method3();
        System.out.println("這是method2執(zhí)行完畢");
    }
    public void method3(){
        System.out.println("這是method3即將執(zhí)行");
        int I=10;
        int j=11;
        System.out.println("這是method3執(zhí)行完畢");
    }
}

1、在IDEA利用斷點(diǎn)進(jìn)行debug模式,觀察棧幀的入棧出棧

在代碼某處加入紅色斷點(diǎn)


image.png

右鍵,進(jìn)入debug模式


image.png

在下方可以觀察debug窗口


image.png

點(diǎn)擊箭頭朝下的藍(lán)色按鈕,執(zhí)行下一條語(yǔ)句


image.png

2、在IDEA中使用javap指令對(duì)class文件進(jìn)行解析

對(duì)上面這段代碼進(jìn)行complie后,會(huì)生成.class文件,生成的.class文件在out/production文件夾下,其中l(wèi)earnJVMdemo是你創(chuàng)建的IDEA項(xiàng)目的名稱。


image.png

在IDEA的Terminal輸入指令


image.png

然后輸入反編譯指令,對(duì)class文件進(jìn)行反編譯


image.png

反編譯輸入的結(jié)果是(仔細(xì)分析反編譯的結(jié)果,能看到學(xué)習(xí)jvm途中遇見(jiàn)的很多老朋友,例如常量池、局部變量表、<init>方法等):

a1234@MacBook-Pro learnJVMdemo % javap -v TestStackFrame.class
Classfile /Users/a1234/IDEA_project/learnJVMdemo/out/production/learnJVMdemo/TestStackFrame.class
  Last modified 2020年5月21日; size 1446 bytes
  SHA-256 checksum 5c1b47cc1ffe73348dbbc7c2713bff73502254e51e2e528f33c84315f11f2f17
  Compiled from "TestStackFrame.java"
public class TestStackFrame
  minor version: 0
  major version: 58
  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
  this_class: #21                         // TestStackFrame
  super_class: #2                         // java/lang/Object
  interfaces: 0, fields: 0, methods: 5, attributes: 1
Constant pool:
   #1 = Methodref          #2.#3          // java/lang/Object."<init>":()V
   #2 = Class              #4             // java/lang/Object
   #3 = NameAndType        #5:#6          // "<init>":()V
   #4 = Utf8               java/lang/Object
   #5 = Utf8               <init>
   #6 = Utf8               ()V
   #7 = Fieldref           #8.#9          // java/lang/System.out:Ljava/io/PrintStream;
   #8 = Class              #10            // java/lang/System
   #9 = NameAndType        #11:#12        // out:Ljava/io/PrintStream;
  #10 = Utf8               java/lang/System
  #11 = Utf8               out
  #12 = Utf8               Ljava/io/PrintStream;
  #13 = String             #14            // 這是main即將執(zhí)行
  #14 = Utf8               這是main即將執(zhí)行
  #15 = Methodref          #16.#17        // java/io/PrintStream.println:(Ljava/lang/String;)V
  #16 = Class              #18            // java/io/PrintStream
  #17 = NameAndType        #19:#20        // println:(Ljava/lang/String;)V
  #18 = Utf8               java/io/PrintStream
  #19 = Utf8               println
  #20 = Utf8               (Ljava/lang/String;)V
  #21 = Class              #22            // TestStackFrame
  #22 = Utf8               TestStackFrame
  #23 = Methodref          #21.#3         // TestStackFrame."<init>":()V
  #24 = Methodref          #21.#25        // TestStackFrame.method1:()V
  #25 = NameAndType        #26:#6         // method1:()V
  #26 = Utf8               method1
  #27 = Class              #28            // java/lang/Exception
  #28 = Utf8               java/lang/Exception
  #29 = Methodref          #27.#30        // java/lang/Exception.printStackTrace:()V
  #30 = NameAndType        #31:#6         // printStackTrace:()V
  #31 = Utf8               printStackTrace
  #32 = Methodref          #16.#33        // java/io/PrintStream.println:()V
  #33 = NameAndType        #19:#6         // println:()V
  #34 = String             #35            // 這是main執(zhí)行完畢
  #35 = Utf8               這是main執(zhí)行完畢
  #36 = String             #37            // 這是method1即將執(zhí)行
  #37 = Utf8               這是method1即將執(zhí)行
  #38 = Methodref          #21.#39        // TestStackFrame.method2:()V
  #39 = NameAndType        #40:#6         // method2:()V
  #40 = Utf8               method2
  #41 = String             #42            // 這是method1執(zhí)行完畢
  #42 = Utf8               這是method1執(zhí)行完畢
  #43 = String             #44            // 這是method2即將執(zhí)行
  #44 = Utf8               這是method2即將執(zhí)行
  #45 = Methodref          #21.#46        // TestStackFrame.method3:()V
  #46 = NameAndType        #47:#6         // method3:()V
  #47 = Utf8               method3
  #48 = String             #49            // 這是method2執(zhí)行完畢
  #49 = Utf8               這是method2執(zhí)行完畢
  #50 = String             #51            // 這是method3即將執(zhí)行
  #51 = Utf8               這是method3即將執(zhí)行
  #52 = String             #53            // 這是method3執(zhí)行完畢
  #53 = Utf8               這是method3執(zhí)行完畢
  #54 = Utf8               Code
  #55 = Utf8               LineNumberTable
  #56 = Utf8               LocalVariableTable
  #57 = Utf8               this
  #58 = Utf8               LTestStackFrame;
  #59 = Utf8               main
  #60 = Utf8               ([Ljava/lang/String;)V
  #61 = Utf8               e
  #62 = Utf8               Ljava/lang/Exception;
  #63 = Utf8               args
  #64 = Utf8               [Ljava/lang/String;
  #65 = Utf8               tt
  #66 = Utf8               StackMapTable
  #67 = Class              #64            // "[Ljava/lang/String;"
  #68 = Utf8               i
  #69 = Utf8               I
  #70 = Utf8               j
  #71 = Utf8               SourceFile
  #72 = Utf8               TestStackFrame.java
{
  public TestStackFrame();
    descriptor: ()V
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 9: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   LTestStackFrame;

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=3, args_size=1
         0: getstatic     #7                  // Field java/lang/System.out:Ljava/io/PrintStream;
         3: ldc           #13                 // String 這是main即將執(zhí)行
         5: invokevirtual #15                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         8: new           #21                 // class TestStackFrame
        11: dup
        12: invokespecial #23                 // Method "<init>":()V
        15: astore_1
        16: aload_1
        17: invokevirtual #24                 // Method method1:()V
        20: goto          28
        23: astore_2
        24: aload_2
        25: invokevirtual #29                 // Method java/lang/Exception.printStackTrace:()V
        28: aload_1
        29: invokevirtual #24                 // Method method1:()V
        32: getstatic     #7                  // Field java/lang/System.out:Ljava/io/PrintStream;
        35: invokevirtual #32                 // Method java/io/PrintStream.println:()V
        38: getstatic     #7                  // Field java/lang/System.out:Ljava/io/PrintStream;
        41: ldc           #34                 // String 這是main執(zhí)行完畢
        43: invokevirtual #15                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        46: return
      Exception table:
         from    to  target type
            16    20    23   Class java/lang/Exception
      LineNumberTable:
        line 13: 0
        line 14: 8
        line 16: 16
        line 19: 20
        line 17: 23
        line 18: 24
        line 20: 28
        line 21: 32
        line 22: 38
        line 23: 46
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
           24       4     2     e   Ljava/lang/Exception;
            0      47     0  args   [Ljava/lang/String;
           16      31     1    tt   LTestStackFrame;
      StackMapTable: number_of_entries = 2
        frame_type = 255 /* full_frame */
          offset_delta = 23
          locals = [ class "[Ljava/lang/String;", class TestStackFrame ]
          stack = [ class java/lang/Exception ]
        frame_type = 4 /* same */

  public void method1();
    descriptor: ()V
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=2, locals=3, args_size=1
         0: getstatic     #7                  // Field java/lang/System.out:Ljava/io/PrintStream;
         3: ldc           #36                 // String 這是method1即將執(zhí)行
         5: invokevirtual #15                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         8: bipush        10
        10: istore_1
        11: bipush        11
        13: istore_2
        14: aload_0
        15: invokevirtual #38                 // Method method2:()V
        18: getstatic     #7                  // Field java/lang/System.out:Ljava/io/PrintStream;
        21: ldc           #41                 // String 這是method1執(zhí)行完畢
        23: invokevirtual #15                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        26: return
      LineNumberTable:
        line 26: 0
        line 27: 8
        line 28: 11
        line 29: 14
        line 32: 18
        line 33: 26
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      27     0  this   LTestStackFrame;
           11      16     1     I   I
           14      13     2     j   I

  public void method2();
    descriptor: ()V
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=2, locals=3, args_size=1
         0: getstatic     #7                  // Field java/lang/System.out:Ljava/io/PrintStream;
         3: ldc           #43                 // String 這是method2即將執(zhí)行
         5: invokevirtual #15                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         8: bipush        10
        10: istore_1
        11: bipush        11
        13: istore_2
        14: aload_0
        15: invokevirtual #45                 // Method method3:()V
        18: getstatic     #7                  // Field java/lang/System.out:Ljava/io/PrintStream;
        21: ldc           #48                 // String 這是method2執(zhí)行完畢
        23: invokevirtual #15                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        26: return
      LineNumberTable:
        line 35: 0
        line 36: 8
        line 37: 11
        line 38: 14
        line 39: 18
        line 40: 26
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      27     0  this   LTestStackFrame;
           11      16     1     I   I
           14      13     2     j   I

  public void method3();
    descriptor: ()V
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=2, locals=3, args_size=1
         0: getstatic     #7                  // Field java/lang/System.out:Ljava/io/PrintStream;
         3: ldc           #50                 // String 這是method3即將執(zhí)行
         5: invokevirtual #15                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         8: bipush        10
        10: istore_1
        11: bipush        11
        13: istore_2
        14: getstatic     #7                  // Field java/lang/System.out:Ljava/io/PrintStream;
        17: ldc           #52                 // String 這是method3執(zhí)行完畢
        19: invokevirtual #15                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        22: return
      LineNumberTable:
        line 42: 0
        line 43: 8
        line 44: 11
        line 45: 14
        line 46: 22
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      23     0  this   LTestStackFrame;
           11      12     1     I   I
           14       9     2     j   I
}
SourceFile: "TestStackFrame.java"
a1234@MacBook-Pro learnJVMdemo % 

3、在IDEA中利用jclasslib插件解析.class文件

首先需要在IDEA中安裝jclasslib插件。進(jìn)入IDEA的設(shè)置


image.png

在marketpalce中搜索jclasslib然后進(jìn)行安裝


在marketpalce中搜索jclasslib然后進(jìn)行安裝

安裝好之后jclasslib出現(xiàn)在installed界面
安裝好之后jclasslib出現(xiàn)在installed界面

重啟IDEA,然后打開(kāi)一個(gè)項(xiàng)目代碼,在view窗口有一個(gè)show bytecode with jclasslib

image.png

點(diǎn)擊,出現(xiàn)下面的界面,就可以從中獲取到class文件相關(guān)的信息了


image.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容