Java 虛擬機(jī)(一):Java 字節(jié)碼

Java 字節(jié)碼

Java 字節(jié)碼是 JVM 里面指令的型式, Java 的源碼經(jīng)過 Java 編譯器會(huì)形成 Java 字節(jié)碼,這的字節(jié)碼才能在 Java 虛擬機(jī)中運(yùn)行伏伐。


java_byte_1.png

一宠进、椀唐鳎基架構(gòu)

一個(gè)虛擬機(jī)有基于棧虛擬機(jī)(Stack based Virtual Machine)和 基于寄存器虛擬機(jī)(Register based Virtual Machine)之法, 它們的差別可以看這里掂为。

Java 的虛擬機(jī)是基于棧的, 它包含 PC 寄存器欲诺、 JVM 棧毅厚、堆和方法區(qū)


java_byte_2.png

注:圖片來自于 極客時(shí)間專欄《深入拆解 Java 虛擬機(jī)》

  • PC 寄存器(program counter): Java 程序里面的每一個(gè)運(yùn)行的線程伴网,都有一個(gè) PC 寄存器存儲(chǔ)著當(dāng)前指令的地址动分。

  • JVM 棧:對(duì)于每一個(gè)線程纠脾,棧 是用來存放局部變量、方法參數(shù)以及返回值的

  • :所有線程共享的內(nèi)存區(qū)域,存放著對(duì)象(類的實(shí)例化和數(shù)組)。對(duì)象由垃圾回收器進(jìn)行再分配

  • 方法區(qū):對(duì)于每一個(gè)加載的類,方法區(qū)里面都存放著方法的代碼茶行,以及符號(hào)表(對(duì)象或字段的引用)以及常量池中的常量

JVM 的棧是由一系列的 Frame 組成的看锉,它包含

java_byte_3.png

注:圖片來自JVM 內(nèi)部原理(六)— Java 字節(jié)碼基礎(chǔ)之一

  • 一個(gè)局部變量數(shù)組(Local Variables), 索引從 0 到數(shù)組長(zhǎng)度減一趾诗。數(shù)據(jù)的長(zhǎng)度由編譯器計(jì)算。除了 longdouble 類型值需要兩個(gè)局部變量的空間存儲(chǔ)外,其他類型的值都可以存儲(chǔ)在一個(gè)局部變量里;

  • 一個(gè)用來存儲(chǔ)中間變量的操作棧(Operand Stack)。該中間變量的作用充當(dāng)指令的操作數(shù),或者存放方法調(diào)用的參數(shù)。它是一個(gè)后進(jìn)先出(LIFO)棧

二、JVM 數(shù)據(jù)類型

JVM 定義的數(shù)據(jù)類型有:

  • 基本數(shù)據(jù)類型:
    • 數(shù)字類型
類型 位數(shù)
byte 8位
short 16位
int 32 位
long 64 位
char 16 位
float 32 位 單精度
double 64 位 雙精度
  • boolean 類型

  • returenAdress: 指令指針默蚌,指向一條虛擬機(jī)指令的操作碼

  • 引用類型

    • 類類型 class type
    • 集合類型 array type
    • 接口類型 interface type

三、指令

Java 字節(jié)碼的指令有一個(gè) JVM 數(shù)據(jù)類型前綴和操作名組成,例如 idd 指令是由 "i" 表示 int 類型數(shù)據(jù)和 “add"相加操作組成,因此 iadd 表示對(duì) int 類型數(shù)值求和瞳秽。

根據(jù)指令的性質(zhì),可以分為以下類型:

  • 加載和存儲(chǔ)指令
  • 運(yùn)算指令
  • 轉(zhuǎn)移指令
  • 對(duì)象創(chuàng)建和訪問指令
  • 操作數(shù)棧管理指令
  • 控制轉(zhuǎn)移指令
  • 方法調(diào)用和返回指令
  • 異常處理指令
  • 同步指令

下面有詳細(xì)的說明

1.加載和存儲(chǔ)指令

加載和存儲(chǔ)指令用于數(shù)據(jù)在棧幀(Frame)中的局部變量數(shù)組(Local Variables)和操作棧(Operand Stack)之間來回傳輸连霉;

具體為:

  • 將一個(gè)局部變量加載到操作棧: iload, xxxload
  • 將一個(gè)數(shù)值從操作數(shù)棧存儲(chǔ)到局部變量表: istore, xxxstore
  • 將一個(gè)常量加載到操作數(shù)棧:bipush, xxxpush, iconst_xxx, ladc_w, ladc2_w, aconst_null 等
  • 擴(kuò)充局部變量表的訪問索引的指令: wide

例如:
例子1:
Calc.java 文件

public class Calc {
    public int calc(){
        int a = 100;
        int b = 200;
        int c = 300;
        return (a + b ) * c;
    }
}

通過命令

javac Calc.java

會(huì)生成 Calc.class 文件
然后在通過命令 javap 可以看到相應(yīng)的字節(jié)碼

javap -v Calc.class

相應(yīng)的字節(jié)碼

  public int calc();
    descriptor: ()I
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=4, args_size=1
         0: bipush        100
         2: istore_1
         3: sipush        200
         6: istore_2
         7: sipush        300
        10: istore_3
        11: iload_1
        12: iload_2
        13: iadd
        14: iload_3
        15: imul
        16: ireturn

執(zhí)行過程

java_byte_4.png
java_byte_5.png
java_byte_6.png

注:圖片來自于周志明《深入理解 Java 虛擬機(jī)》

2.運(yùn)算指令

運(yùn)算指令用于對(duì)兩個(gè)操作棧上的值進(jìn)行某種特定運(yùn)算,并把結(jié)果重新存入到操作棧頂箭阶。
分為兩類:對(duì)整形數(shù)據(jù)進(jìn)行運(yùn)算的指令和對(duì)浮點(diǎn)型數(shù)據(jù)進(jìn)行運(yùn)算的指令罩扇。

  • 加法指令: iadd, ladd, fadd, dadd
  • 減法指令: isub, lsub, fsub, dsub
  • 乘法指令: imul, lmul, fmul, dmul
  • 除法指令: idiv, ldiv, fdiv, ddiv
  • 求余指令: irem, lrem, frem, drem
  • 取反指令: ineg, lneg, fneg, dneg
  • 位移指令: ishl, ishr, iushr, lshl, lshr, lushr
  • 按位或指令:ior, lor
  • 按位與指令: iand, land
  • 按位異或指令:ixor, lxor
  • 局部變量自增指令:iinc
  • 比較指令:dcmpg, dcmpl, fcmpg, fcmpl, lcmp

上面例子1中的執(zhí)行偏移地址13指令 iadd 就是將操作棧頂中兩個(gè)數(shù) 200 加上 100, 再把它的和 300 壓回棧滩届。

在除非指令(idiv, ldiv)以及求余指令(irem 和 lrem )中命浴, 當(dāng)出現(xiàn)除數(shù)為零時(shí)會(huì)導(dǎo)致虛擬機(jī)拋出 ArithmeticException 異常

3.轉(zhuǎn)換指令

轉(zhuǎn)換指令可以將兩種不同的數(shù)值類型進(jìn)行相互轉(zhuǎn)換月幌,一般用于顯示類型轉(zhuǎn)換
包含: i2b, i2c, i2s, l2i, f2i, f2l, d2i, d2l 和 d2f
其中 i 是 int, b 是 byte, c 是 char, s 是 short, l 是long, f 是 float, d 是 double 類型

例子2:
java 源碼

public class Test {
    public static void main(String[] args) {
            long zz = 10000;
            int yy = (int)zz;
            int a = 1;
            int b = 2;
            int c = a + b;
        }
}

用 javap 生成的字節(jié)碼是

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=7, args_size=1
         0: ldc2_w        #2                  // long 10000l , 將常量 1000l 加載到操作棧
         3: lstore_1
         4: lload_1
         5: l2i         // 這里對(duì)應(yīng) int yy = (int)zz; 進(jìn)行強(qiáng)轉(zhuǎn)
         6: istore_3
         7: iconst_1
         8: istore        4
        10: iconst_2
        11: istore        5
        13: iload         4
        15: iload         5
        17: iadd
        18: istore        6
        20: return
}

4.對(duì)象創(chuàng)建與訪問指令

在 Java 中一切皆為對(duì)象,類實(shí)例和數(shù)組都是對(duì)象鳄虱,但是 Java 虛擬機(jī)對(duì)類實(shí)例和數(shù)組的創(chuàng)建與操作使用了不同的字節(jié)碼指令倍踪。

  • 創(chuàng)建類實(shí)例的指令: new
  • 創(chuàng)建數(shù)組的指令: newarray, anewarry, multianewarray
  • 訪問類字段(static 字段)和實(shí)例字段(非 static 字段)的指令: getfield, putfield, getstatic, putstatic
  • 把一個(gè)數(shù)組元素加載到操作棧的指令: baload, caload, saload, iaload, laload, faload, daload, aaload
  • 把一個(gè)操作數(shù)棧的值存儲(chǔ)到數(shù)組元素中的指令: bastore, castore, sastore, iastore, fastore, dastore, aastore
  • 取數(shù)組長(zhǎng)度的指令 : arraylength
  • 檢查類實(shí)例類型的指令: instanceof, checkcast

例3:

public class Test {

    public static void main(String[] args) {
        ByteTest byteTest = new ByteTest();
        byteTest.name = "zhangsan";
        byteTest.age = 13;

        String[] list = new String[1];
        list[0] = "one";
        int size = list.length;
    }

    public static class ByteTest{

        public static String name;

        public int age;
    }
}

生成的部分字節(jié)碼

 public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=3, locals=4, args_size=1
         0: new           #2                  // new 指令嫉到,new 一個(gè) ByteTest 對(duì)象
         3: dup
         4: invokespecial #3                  // Method com/yxhuang/temp/Test$ByteTest."<init>":()V
         7: astore_1
         8: aload_1
         9: pop
        10: ldc           #4                  // String zhangsan
        12: putstatic     #5                  // 訪問 ByteTest 靜態(tài)字段 name
        15: aload_1
        16: bipush        13
        18: putfield      #6                  // 訪問 ByteTest 實(shí)例的字段 age
        21: iconst_1
        22: anewarray     #7                  // 創(chuàng)建數(shù)組
        25: astore_2
        26: aload_2
        27: iconst_0
        28: ldc           #8                  // String one
        30: aastore
        31: aload_2
        32: arraylength                     // 取數(shù)組的長(zhǎng)度
        33: istore_3
        34: return

5.操作數(shù)棧管理指令

包括

  • 將操作數(shù)棧的棧頂一個(gè)或兩個(gè)元素出棧: pop, pop2
  • 復(fù)制棧頂一個(gè)或兩個(gè)數(shù)值并將復(fù)制值或雙份的復(fù)制值重新壓入棧頂:dup, dup2, dup_x1, dup_x2, dup2_x1, dup2_x2;
  • 將棧最頂端的兩個(gè)數(shù)值互換: swap

其中 pop 是將棧頂一個(gè)元素出棧,pop2 是將棧頂?shù)膬蓚€(gè)元素出棧陌僵;

dup 是復(fù)制棧頂數(shù)值并將復(fù)制值壓入棧頂, dup2 是復(fù)制棧頂一個(gè)(對(duì)于 long 或 double 類型)或 兩個(gè)(非 long, double 類型)的數(shù)值彈出;

dup_x1 是復(fù)制棧頂?shù)闹挡蓚€(gè)復(fù)制值壓入棧頂正蛙,dup_x2 復(fù)制棧頂一個(gè)(對(duì)于 long 或 double 類型)或 兩個(gè)(非 long, double 類型)的數(shù)值并壓入棧頂蒂阱;

dup2_x1 是 dup_x1 的雙倍版本响委, dup2_x2 是 dup_x2 的雙倍版本夹囚;

java_byte_7.jpg

注:圖片來自于JVM 內(nèi)部原理(六)— Java 字節(jié)碼基礎(chǔ)之一

在 java 中 long 和 double 類型需要占用兩個(gè)存儲(chǔ)空間扇救,為了交換兩個(gè) double 值徽千,需要 dup2_x2

java_byte_8.png

6.控制轉(zhuǎn)移指令

控制轉(zhuǎn)移指令可以讓 Java 虛擬機(jī)有條件或無條件地從指定的位置指令而不是控制轉(zhuǎn)移指令的下一條指令繼續(xù)執(zhí)行程序

  • 條件分支
指令 例子 說明
ifeq if (i == 0)
if (bool == false)
當(dāng)棧頂 int 型數(shù)值等于0 或者是 false 跳轉(zhuǎn)
ifne if (i != 0)
if (bool == true)
當(dāng)棧頂 int 型數(shù)值不等于0 或者是 true 跳轉(zhuǎn)
ifge if (i >= 0) 當(dāng)棧頂 int 型數(shù)值大于或等于0時(shí)跳轉(zhuǎn)
ifgt if (i > 0) 當(dāng)棧頂 int 型數(shù)值大于0時(shí)跳轉(zhuǎn)
ifle if (i <= 0) 當(dāng)棧頂 int 型數(shù)值小于或等于0時(shí)跳轉(zhuǎn)
iflt if (i < 0) 當(dāng)棧頂 int 型數(shù)值小于0時(shí)跳轉(zhuǎn)
if_icmple 比較棧頂兩個(gè) int 型數(shù)值的大小,當(dāng)結(jié)果小于或等于0時(shí)跳轉(zhuǎn)
  • 復(fù)合條件分支

    • tableswitch, 用于 switch 條件跳轉(zhuǎn)锨并, case 值連續(xù)(可變長(zhǎng)度指令)
    • lookupswitch, 用于 switch 條件跳轉(zhuǎn)露该, case 值不連續(xù)(可變長(zhǎng)度指令)
  • 無條件分支

    • goto, 無條件跳轉(zhuǎn)

在 Java 虛擬機(jī)中,各種類型的比較最終都會(huì)轉(zhuǎn)化為 int 類型的比較第煮。

例4:

static int gt(int a, int b){
    if (a > b){
        return 1;
    } else {
        return -1;
    }
}

// 生成的字節(jié)碼
  static int gt(int, int);
    descriptor: (II)I
    flags: ACC_STATIC
    Code:
      stack=2, locals=2, args_size=2
         0: iload_0                 // 將 a 入棧 local[0]{a}
         1: iload_1                 // 將 b 入棧 local[1]解幼
         2: if_icmple     7         // 如果 local[0] <= local[1] 跳去 7 抑党,即 iconst_m1
         5: iconst_1     // 將 int 型 1 推送至棧頂
         6: ireturn      // 返回
         7: iconst_m1    // 將 int 型 -1 推送至棧頂
         8: ireturn      // 返回

注意上面的 if_icmple 指令是比較棧頂兩個(gè) int 型數(shù)值的大小,當(dāng)結(jié)果小于或等于0時(shí)跳轉(zhuǎn)撵摆, 與我們代碼中 a > b 剛好是相反的



例5:

 static int calc(int count){
        int result = 0;
        while (count > 0){
            result += count--;
        }
        return result;
    }
    
// 字節(jié)碼
 static int calc(int);
    descriptor: (I)I
    flags: ACC_STATIC
    Code:
      stack=2, locals=2, args_size=1
         0: iconst_0        // count 入棧
         1: istore_1
         2: iload_0
         3: ifle          16   // 當(dāng)棧頂數(shù)值小于或等于0時(shí)調(diào)到 16底靠, 即跳出 while 選好
         6: iload_1
         7: iload_0
         8: iinc          0, -1   // 自增或自減, 即 count--   
        11: iadd            // result+
        12: istore_1
        13: goto          2 // 回到 2
        16: iload_1
        17: ireturn

例6:

 static int calcSwitch(int type){
        int result = 0;
        switch (type){
            case 1:
                result = 10;
                break;
            case 2:
                result = 11;
                break;
        }
        return result;
    }

// 字節(jié)碼
static int calcSwitch(int);
    descriptor: (I)I
    flags: ACC_STATIC
    Code:
      stack=1, locals=2, args_size=1
         0: iconst_0
         1: istore_1
         2: iload_0
         3: lookupswitch  { // 2
                       1: 28
                       2: 34
                 default: 37
            }
        28: bipush        10
        30: istore_1
        31: goto          37
        34: bipush        11
        36: istore_1
        37: iload_1
        38: ireturn

7.方法調(diào)用和返回指令

  • invokevirtual 指令用于調(diào)用對(duì)象的實(shí)例方法特铝,根據(jù)對(duì)象的實(shí)際類型進(jìn)行分派暑中;
  • invokeinterface 指令用于調(diào)用接口方法,會(huì)在運(yùn)行時(shí)搜索一個(gè)實(shí)現(xiàn)了這個(gè)接口方法的對(duì)象鲫剿,找出合適的方法進(jìn)行調(diào)用鳄逾;
  • invokespecial 指令用于調(diào)用一些需要特效處理的實(shí)例方法,包括實(shí)例初始化方法牵素、私有方法和父類方法
  • invokestatic 指令調(diào)用類方法(static 方法)
  • invokedynamic 指令用于在運(yùn)行時(shí)動(dòng)態(tài)解析出調(diào)用點(diǎn)限定符所引用的方法严衬,并執(zhí)行該方法

8.異常處理指令

arthrow 指令是 Java 程序中顯式拋出異常的操作(throw 語句)

9.同步指令

同步一段指令集序列通常是由 Java 語言中的 synchroined 語句來表示, Java 虛擬機(jī)的指令集中有 monitorenter 和 monitorexit 兩條指令來支持 synchronizd.

例7:

  static void sycn(Object object){
       synchronized (object){

       }
   }
   
   // 相應(yīng)的字節(jié)碼
   static void sycn(java.lang.Object);
   descriptor: (Ljava/lang/Object;)V
   flags: ACC_STATIC
   Code:
     stack=2, locals=3, args_size=1
        0: aload_0
        1: dup
        2: astore_1
        3: monitorenter
        4: aload_1
        5: monitorexit
        6: goto          14
        9: astore_2
       10: aload_1
       11: monitorexit
       12: aload_2
       13: athrow
       14: return

每條 monitorenter 指令都必須有其對(duì)應(yīng)的 monitorexit 指令笆呆,上面例子中的 3 和 5 是對(duì)應(yīng)的请琳。9 是處理異常的,這是編譯器會(huì)自動(dòng)產(chǎn)生一個(gè)異常處理赠幕,同步指令也需要在異常的時(shí)候退出俄精,11 monitorexit 就是編譯器自動(dòng)生成在異常時(shí)退出的指令。

四榕堰、參考

1.【譯】如何閱讀 Java 字節(jié)碼

  1. JVM 內(nèi)部原理(六)— Java 字節(jié)碼基礎(chǔ)之一

  2. 周志明《深入理解 Java 虛擬機(jī)》

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末竖慧,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子逆屡,更是在濱河造成了極大的恐慌圾旨,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,546評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件魏蔗,死亡現(xiàn)場(chǎng)離奇詭異砍的,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)莺治,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門廓鞠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人谣旁,你說我怎么就攤上這事床佳。” “怎么了榄审?”我有些...
    開封第一講書人閱讀 164,911評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵砌们,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng)怨绣,這世上最難降的妖魔是什么角溃? 我笑而不...
    開封第一講書人閱讀 58,737評(píng)論 1 294
  • 正文 為了忘掉前任拷获,我火速辦了婚禮篮撑,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘匆瓜。我一直安慰自己赢笨,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,753評(píng)論 6 392
  • 文/花漫 我一把揭開白布驮吱。 她就那樣靜靜地躺著茧妒,像睡著了一般。 火紅的嫁衣襯著肌膚如雪左冬。 梳的紋絲不亂的頭發(fā)上桐筏,一...
    開封第一講書人閱讀 51,598評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音拇砰,去河邊找鬼梅忌。 笑死,一個(gè)胖子當(dāng)著我的面吹牛除破,可吹牛的內(nèi)容都是我干的牧氮。 我是一名探鬼主播,決...
    沈念sama閱讀 40,338評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼瑰枫,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼踱葛!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起光坝,我...
    開封第一講書人閱讀 39,249評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤尸诽,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后盯另,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體性含,經(jīng)...
    沈念sama閱讀 45,696評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,888評(píng)論 3 336
  • 正文 我和宋清朗相戀三年土铺,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了胶滋。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,013評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡悲敷,死狀恐怖究恤,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情后德,我是刑警寧澤部宿,帶...
    沈念sama閱讀 35,731評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響理张,放射性物質(zhì)發(fā)生泄漏赫蛇。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,348評(píng)論 3 330
  • 文/蒙蒙 一雾叭、第九天 我趴在偏房一處隱蔽的房頂上張望悟耘。 院中可真熱鬧,春花似錦织狐、人聲如沸暂幼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽旺嬉。三九已至,卻和暖如春厨埋,著一層夾襖步出監(jiān)牢的瞬間邪媳,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評(píng)論 1 270
  • 我被黑心中介騙來泰國打工荡陷, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留雨效,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,203評(píng)論 3 370
  • 正文 我出身青樓亲善,卻偏偏與公主長(zhǎng)得像设易,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蛹头,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,960評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 字節(jié)碼與數(shù)據(jù)類型 在Java虛擬機(jī)的指令集中顿肺,大多數(shù)的指令都包含了其操作所對(duì)應(yīng)的數(shù)據(jù)類型信息。 加載和存儲(chǔ)指令 加...
    itcayman閱讀 1,509評(píng)論 0 0
  • Java虛擬機(jī)的指令由一個(gè)字節(jié)長(zhǎng)度的渣蜗、代表著某種特定操作含義的數(shù)字(操作碼屠尊,Opcode)以及跟隨其后的零至多個(gè)代...
    塞外的風(fēng)閱讀 3,481評(píng)論 0 3
  • 即便對(duì)那些有經(jīng)驗(yàn)的Java開發(fā)人員來說讼昆,閱讀已編譯的Java字節(jié)碼也很乏味。為什么我們首先需要了解這種底層的東西骚烧?...
    怪物小姐姐閱讀 606評(píng)論 0 8
  • Idea 配置腳本 調(diào)用腳本 解讀腳本 java程序源碼 jdk1.10代碼反編譯結(jié)果 jdk1.8反編譯結(jié)果 字...
    厭惡狡詐心機(jī)閱讀 1,056評(píng)論 0 2
  • 妹的浸赫!飯錢從六十多塊跳水到四十多,太坑了赃绊,后臺(tái)系統(tǒng)動(dòng)動(dòng)手腳沒人會(huì)知道的既峡,一個(gè)十來塊不等,一萬個(gè)一天就是十幾萬碧查,賺錢...
    杰杰6889閱讀 259評(píng)論 0 0