1. <ul id="0c1fb"></ul>

      <noscript id="0c1fb"><video id="0c1fb"></video></noscript>
      <noscript id="0c1fb"><listing id="0c1fb"><thead id="0c1fb"></thead></listing></noscript>

      99热在线精品一区二区三区_国产伦精品一区二区三区女破破_亚洲一区二区三区无码_精品国产欧美日韩另类一区

      RELATEED CONSULTING
      相關(guān)咨詢
      選擇下列產(chǎn)品馬上在線溝通
      服務(wù)時(shí)間:8:30-17:00
      你可能遇到了下面的問題
      關(guān)閉右側(cè)工具欄

      新聞中心

      這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
      Java字節(jié)碼的知識(shí)點(diǎn)有哪些

      這篇文章主要為大家展示了“Java字節(jié)碼的知識(shí)點(diǎn)有哪些”,內(nèi)容簡(jiǎn)而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“Java字節(jié)碼的知識(shí)點(diǎn)有哪些”這篇文章吧。

      成都創(chuàng)新互聯(lián)公司是一家朝氣蓬勃的網(wǎng)站建設(shè)公司。公司專注于為企業(yè)提供信息化建設(shè)解決方案。從事網(wǎng)站開發(fā),網(wǎng)站制作,網(wǎng)站設(shè)計(jì),網(wǎng)站模板,微信公眾號(hào)開發(fā),軟件開發(fā),微信平臺(tái)小程序開發(fā),十余年建站對(duì)護(hù)欄打樁機(jī)等多個(gè)行業(yè),擁有豐富的網(wǎng)站營銷經(jīng)驗(yàn)。

      編譯“1+1”代碼

      首先我們需要寫個(gè)簡(jiǎn)單的小程序,1+1的程序,學(xué)習(xí)就要從最簡(jiǎn)單的1+1開始,代碼如下:

      package top.luozhou.test;/**
       * @description:
       * @author: luozhou
       * @create: 2019-12-25 21:28
       **/public class TestJava {    
           public static void main(String[] args) {
               int a=1+1;
              System.out.println(a);
          }
      }

      寫好java類文件后,首先執(zhí)行命令javac TestJava.java 編譯類文件,生成TestJava.class。 然后執(zhí)行反編譯命令javap -verbose TestJava,字節(jié)碼結(jié)果顯示如下:

        Compiled from "TestJava.java"public class top.luozhou.test.TestJava
        minor version: 0
        major version: 56
        flags: ACC_PUBLIC, ACC_SUPER
      Constant pool:
         #1 = Methodref          #5.#14         // java/lang/Object."":()V
         #2 = Fieldref           #15.#16        // java/lang/System.out:Ljava/io/PrintStream;
         #3 = Methodref          #17.#18        // java/io/PrintStream.println:(I)V
         #4 = Class              #19            // top/luozhou/test/TestJava
         #5 = Class              #20            // java/lang/Object
         #6 = Utf8               
         #7 = Utf8               ()V
         #8 = Utf8               Code
         #9 = Utf8               LineNumberTable
        #10 = Utf8               main
        #11 = Utf8               ([Ljava/lang/String;)V
        #12 = Utf8               SourceFile
        #13 = Utf8               TestJava.java
        #14 = NameAndType        #6:#7          // "":()V
        #15 = Class              #21            // java/lang/System
        #16 = NameAndType        #22:#23        // out:Ljava/io/PrintStream;
        #17 = Class              #24            // java/io/PrintStream
        #18 = NameAndType        #25:#26        // println:(I)V
        #19 = Utf8               top/luozhou/test/TestJava
        #20 = Utf8               java/lang/Object
        #21 = Utf8               java/lang/System
        #22 = Utf8               out
        #23 = Utf8               Ljava/io/PrintStream;
        #24 = Utf8               java/io/PrintStream
        #25 = Utf8               println
        #26 = Utf8               (I)V
      {  public top.luozhou.test.TestJava();
          descriptor: ()V
          flags: ACC_PUBLIC
          Code:      stack=1, locals=1, args_size=1
               0: aload_0         1: invokespecial #1                  // Method java/lang/Object."":()V
               4: return
            LineNumberTable:
              line 8: 0
        public static void main(java.lang.String[]);
          descriptor: ([Ljava/lang/String;)V
          flags: ACC_PUBLIC, ACC_STATIC
          Code:      stack=2, locals=2, args_size=1
               0: iconst_2         1: istore_1         2: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
               5: iload_1         6: invokevirtual #3                  // Method java/io/PrintStream.println:(I)V
               9: return
            LineNumberTable:
              line 10: 0
              line 11: 2
              line 12: 9}

      解析字節(jié)碼

      1.基礎(chǔ)信息

      上述結(jié)果刪除了部分不影響解析的冗余信息,接下來我們便來解析字節(jié)碼的結(jié)果。

       minor version: 0 次版本號(hào),為0表示未使用
       major version: 56 主版本號(hào),56表示jdk12,表示只能運(yùn)行在jdk12版本以及之后的虛擬機(jī)中
      flags: ACC_PUBLIC, ACC_SUPER

      ACC_PUBLIC:這就是一個(gè)是否是public類型的訪問標(biāo)志。

      ACC_SUPER: 這個(gè)falg是為了解決通過 invokespecial 指令調(diào)用 super 方法的問題。可以將它理解成 Java 1.0.2 的一個(gè)缺陷補(bǔ)丁,只有通過這樣它才能正確找到 super 類方法。從 Java 1.0.2 開始,編譯器始終會(huì)在字節(jié)碼中生成 ACC_SUPER 訪問標(biāo)識(shí)。感興趣的同學(xué)可以點(diǎn)擊這里來了解更多。

      2.常量池

      接下來,我們將要分析常量池,你也可以對(duì)照上面整體的字節(jié)碼來理解。

      #1 = Methodref          #5.#14         // java/lang/Object."":()V

      這是一個(gè)方法引用,這里的#5表示索引值,然后我們可以發(fā)現(xiàn)索引值為5的字節(jié)碼如下

      #5 = Class              #20            // java/lang/Object

      它表示這是一個(gè)Object類,同理#14指向的是一個(gè)"":()V表示引用的是初始化方法。

      #2 = Fieldref           #15.#16        // java/lang/System.out:Ljava/io/PrintStream;

      上面這段表示是一個(gè)字段引用,同樣引用了#15和#16,實(shí)際上引用的就是java/lang/System類中的PrintStream對(duì)象。其他的常量池分析思路是一樣的,鑒于篇幅我就不一一說明了,只列下其中的幾個(gè)關(guān)鍵類型和信息。

      NameAndType:這個(gè)表示是名稱和類型的常量表,可以指向方法名稱或者字段的索引,在上面的字節(jié)碼中都是表示的實(shí)際的方法。

      Utf8:我們經(jīng)常使用的是字符編碼,但是這個(gè)不是只有字符編碼的意思,它表示一種字符編碼是Utf8的字符串。它是虛擬機(jī)中最常用的表結(jié)構(gòu),你可以理解為它可以描述方法,字段,類等信息。 比如:

      #4 = Class              #19 #19 = Utf8               top/luozhou/test/TestJava

      這里表示#4這個(gè)索引下是一個(gè)類,然后指向的類是#19,#19是一個(gè)Utf8表,最終存放的是top/luozhou/test/TestJava,那么這樣一連接起來就可以知道#4位置引用的類是top/luozhou/test/TestJava了。

      3.構(gòu)造方法信息

      接下來,我們分析下構(gòu)造方法的字節(jié)碼,我們知道,一個(gè)類初始化的時(shí)候最先執(zhí)行它的構(gòu)造方法,如果你沒有寫構(gòu)造方法,系統(tǒng)會(huì)默認(rèn)給你添加一個(gè)無參的構(gòu)造方法。

      public top.luozhou.test.TestJava();    
          descriptor: ()V    flags: ACC_PUBLIC    Code:      stack=1, locals=1, args_size=1
               0: aload_0         
               1: invokespecial #1                  // Method java/lang/Object."":()V
               4: return      LineNumberTable:
              line 8: 0

      descriptor: ()V :表示這是一個(gè)沒有返回值的方法。

      flags: ACC_PUBLIC:是公共方法。

      stack=1, locals=1, args_size=1 :表示棧中的數(shù)量為1,局部變量表中的變量為1,調(diào)用參數(shù)也為1。

      這里為什么都是1呢?這不是默認(rèn)的構(gòu)造方法嗎?哪來的參數(shù)?其實(shí)Java語言有一個(gè)潛規(guī)則:在任何實(shí)例方法里面都可以通過this來訪問到此方法所屬的對(duì)象。而這種機(jī)制的實(shí)現(xiàn)就是通過Java編譯器在編譯的時(shí)候作為入?yún)魅氲椒椒ㄖ辛耍煜ython語言的同學(xué)肯定會(huì)知道,在python中定義一個(gè)方法總會(huì)傳入一個(gè)self的參數(shù),這也是傳入此實(shí)例的引用到方法內(nèi)部,Java只是把這種機(jī)制后推到編譯階段完成而已。所以,這里的1都是指this這個(gè)參數(shù)而已。

               0: aload_0         1: invokespecial #1                  // Method java/lang/Object."":()V
               4: return
          LineNumberTable:        line 8: 0

      經(jīng)過上面這個(gè)分析對(duì)于這個(gè)構(gòu)造方法表達(dá)的意思也就很清晰了。

      aload_0:表示把局部變量表中的第一個(gè)變量加載到棧中,也就是this。

      invokespecial:直接調(diào)用初始化方法。

      return:調(diào)用完畢方法結(jié)束。

      LineNumberTable:這是一個(gè)行數(shù)的表,用來記錄字節(jié)碼的偏移量和代碼行數(shù)的映射關(guān)系。line 8: 0表示,源碼中第8行對(duì)應(yīng)的就是偏移量0的字節(jié)碼,因?yàn)槭悄J(rèn)的構(gòu)造方法,所以這里并無法直觀體現(xiàn)出來。

      另外這里會(huì)執(zhí)行Object的構(gòu)造方法是因?yàn)椋琌bject是所有類的父類,子類的構(gòu)造要先構(gòu)造父類的構(gòu)造方法。

      4.main方法信息

      public static void main(java.lang.String[]);
          descriptor: ([Ljava/lang/String;)V
          flags: ACC_PUBLIC, ACC_STATIC
          Code:
            stack=2, locals=2, args_size=1
               0: iconst_2         1: istore_1         2: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
               5: iload_1         6: invokevirtual #3                  // Method java/io/PrintStream.println:(I)V
               9: return
            LineNumberTable:        line 10: 0
              line 11: 2
              line 12: 9

      有了之前構(gòu)造方法的分析,我們接下來分析main方法也會(huì)熟悉很多,重復(fù)的我就略過了,這里重點(diǎn)分析code部分。

      stack=2, locals=2, args_size=1:這里的棧和局部變量表為2,參數(shù)還是為1。這是為什么呢?因?yàn)閙ain方法中聲明了一個(gè)變量a,所以局部變量表要加一個(gè),棧也是,所以他們是2。那為什么args_size還是1呢?你不是說默認(rèn)會(huì)把this傳入的嗎?應(yīng)該是2啊。注意:之前說的是在任何實(shí)例方法中,而這個(gè)main方法是一個(gè)靜態(tài)方法,靜態(tài)方法直接可以通過類+方法名訪問,并不需要實(shí)例對(duì)象,所以這里就沒必要傳入了。

      0: iconst_2:將int類型2推送到棧頂。

      1: istore_1:將棧頂int類型數(shù)值存入第二個(gè)本地變量。

      2: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;:獲取PrintStream類。

      5: iload_1: 把第二個(gè)int型本地變量推送到棧頂。

      6: invokevirtual #3 // Method java/io/PrintStream.println:(I)V:調(diào)用println方法。

      9: return:調(diào)用完畢結(jié)束方法。

      這里的LineNumberTable是有源碼的,我們可以對(duì)照下我前面描述是否正確:

      Java字節(jié)碼的知識(shí)點(diǎn)有哪些

      line 10: 0: 第10行表示 0: iconst_2字節(jié)碼,這里我們發(fā)現(xiàn)編譯器直接給我們計(jì)算好了把2推送到棧頂了。

      line 11: 2:第11行源碼對(duì)應(yīng)的是 2: getstatic 獲取輸出的靜態(tài)類PrintStream。

      line 12: 9:12行源碼對(duì)應(yīng)的是return,表示方法結(jié)束。

      這里我也畫了一個(gè)動(dòng)態(tài)圖片來演示main方法執(zhí)行的過程,希望能夠幫助你理解:

      Java字節(jié)碼的知識(shí)點(diǎn)有哪些

      以上是“Java字節(jié)碼的知識(shí)點(diǎn)有哪些”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!


      網(wǎng)站標(biāo)題:Java字節(jié)碼的知識(shí)點(diǎn)有哪些
      網(wǎng)站網(wǎng)址:http://www.ef60e0e.cn/article/igihdg.html
      99热在线精品一区二区三区_国产伦精品一区二区三区女破破_亚洲一区二区三区无码_精品国产欧美日韩另类一区
      1. <ul id="0c1fb"></ul>

        <noscript id="0c1fb"><video id="0c1fb"></video></noscript>
        <noscript id="0c1fb"><listing id="0c1fb"><thead id="0c1fb"></thead></listing></noscript>

        新源县| 遂宁市| 阿合奇县| 古田县| 红桥区| 攀枝花市| 新竹县| 乌兰察布市| 东方市| 昭觉县| 乐都县| 巴彦县| 贡山| 南丰县| 山西省| 桃园市| 贵定县| 安乡县| 吉首市| 清镇市| 宜川县| 彝良县| 宁化县| 会泽县| 凤凰县| 汉源县| 长治县| 荥阳市| 乐至县| 吉木萨尔县| 桦南县| 古交市| 保山市| 武川县| 昭通市| 西林县| 阿拉善盟| 北碚区| 云龙县| 维西| 渝中区|