溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Java字節(jié)碼實(shí)例分析

發(fā)布時(shí)間:2022-01-06 20:06:18 來(lái)源:億速云 閱讀:136 作者:iii 欄目:編程語(yǔ)言

這篇文章主要講解了“Java字節(jié)碼實(shí)例分析”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“Java字節(jié)碼實(shí)例分析”吧!

一:Java字節(jié)代碼的組織形式

類文件{

OxCAFEBABE,小版本號(hào),大版本號(hào),常量池大小,常量池?cái)?shù)組,訪問控制標(biāo)記,當(dāng)前類信息,父類信息,實(shí)現(xiàn)的接口個(gè)數(shù),實(shí)現(xiàn)的接口信息數(shù)組,域個(gè)數(shù),域信息數(shù)組,方法個(gè)數(shù),方法信息數(shù)組,屬性個(gè)數(shù),屬性信息數(shù)組

}

二:查看方法 --- javap命令

例子:有一個(gè)Java類Demo.java

public class Demo {     private String str1;     private String str2;     private int num1;     private int num2;     public static final String STATIC_DATA = "hello world";          private void sayHello1(){         System.out.println("this is method1...");     }     private void sayHello2(){         System.out.println("this is method2...");     }     public void sayHello3(){         System.out.println("this is method3...");     } }

通過jdk自帶的反編譯工具命令 javap 可以查看class文件的字節(jié)碼信息

D:\>javap -verbose Demo >> Demo.txt

Demo.txt:

Compiled from "Demo.java" public class Demo extends java.lang.Object   SourceFile: "Demo.java"   minor version: 0   major version: 49       Constant pool: const #1 = class      #2;   //  Demo const #2 = Asciz     Demo; const #3 = class      #4;   //  java/lang/Object const #4 = Asciz     java/lang/Object; const #5 = Asciz     str1; const #6 = Asciz     Ljava/lang/String;; const #7 = Asciz     str2; const #8 = Asciz     num1; const #9 = Asciz     I; const #10 = Asciz   num2; const #11 = Asciz   STATIC_DATA; const #12 = Asciz   ConstantValue; const #13 = String  #14; //  hello world const #14 = Asciz   hello world; const #15 = Asciz   <init>; const #16 = Asciz   ()V; const #17 = Asciz   Code; const #18 = Method       #3.#19;   //  java/lang/Object."<init>":()V const #19 = NameAndType    #15:#16;//  "<init>":()V const #20 = Asciz   LineNumberTable; const #21 = Asciz   LocalVariableTable; const #22 = Asciz   this; const #23 = Asciz   LDemo;; const #24 = Asciz   sayHello1; const #25 = Field   #26.#28;  //  java/lang/System.out:Ljava/io/PrintStream; const #26 = class    #27; //  java/lang/System const #27 = Asciz   java/lang/System; const #28 = NameAndType    #29:#30;//  out:Ljava/io/PrintStream; const #29 = Asciz   out; const #30 = Asciz   Ljava/io/PrintStream;; const #31 = String  #32; //  this is method1... const #32 = Asciz   this is method1...; const #33 = Method       #34.#36;  //  java/io/PrintStream.println:(Ljava/lang/String;)V const #34 = class    #35; //  java/io/PrintStream const #35 = Asciz   java/io/PrintStream; const #36 = NameAndType    #37:#38;//  println:(Ljava/lang/String;)V const #37 = Asciz   println; const #38 = Asciz   (Ljava/lang/String;)V; const #39 = Asciz   sayHello2; const #40 = String  #41; //  this is method2... const #41 = Asciz   this is method2...; const #42 = Asciz   sayHello3; const #43 = String  #44; //  this is method3... const #44 = Asciz   this is method3...; const #45 = Asciz   SourceFile; const #46 = Asciz   Demo.java;   { public static final java.lang.String STATIC_DATA;   Constant value: String hello world public Demo();   Code:    Stack=1, Locals=1, Args_size=1    0:      aload_0    1:      invokespecial  #18; //Method java/lang/Object."<init>":()V    4:      return   LineNumberTable:    line 2: 0   LocalVariableTable:    Start  Length  Slot  Name   Signature    0      5      0    this       LDemo;   public void sayHello3();   Code:    Stack=2, Locals=1, Args_size=1    0:      getstatic   #25; //Field java/lang/System.out:Ljava/io/PrintStream;    3:      ldc   #43; //String this is method3...    5:      invokevirtual  #33; //Method java/io/PrintStream.println:(Ljava/lang/String;)V    8:      return   LineNumberTable:    line 17: 0    line 18: 8   LocalVariableTable:    Start  Length  Slot  Name   Signature    0      9      0    this       LDemo; }

解析:

1.版本號(hào)  major version: 49   //java版本 jdk1.6顯示的是50, jdk1.5顯示的是49,jdk1.4顯示的是58 , 高版本能執(zhí)行低版本的class文件

2.常量池Constant pool

Method:方法

Field:字段

String:字符串

Asciz:簽名如<init>由jvm調(diào)用,其他是不能夠去調(diào)用它的

NameAndType:變量名的類型

Class:類

通過字節(jié)碼,我們可以看到Demo類 繼承于java.lang.Object,如果類中沒有顯式聲明構(gòu)造函數(shù)的話,編譯器會(huì)插入一個(gè)缺省無(wú)參的構(gòu)造函數(shù)(構(gòu)造函數(shù)在JVM級(jí)別是顯示成<init>的普通函數(shù))。

三:檢測(cè)代碼的效率問題

學(xué)習(xí)Java的過程中,都會(huì)了解到字符串合并時(shí)要用到StringBuffer 來(lái)代替String,那下面就來(lái)通過Java字節(jié)碼來(lái)驗(yàn)證兩種方式的效率性。

例子:一個(gè)Java類 TestString.java

<strong>public class TestString {     public String testString(String str1, String str2){        return str1 + str2;     }     public String testStringBuffer(StringBuffer sb, String str){        return sb.append(str).toString();     } }  </strong>

javap &ndash;c TestString 后字節(jié)碼信息:

Compiled from "TestString.java" public class TestString extends java.lang.Object{ public TestString();   Code:    0:      aload_0    1:      invokespecial  #8; //Method java/lang/Object."<init>":()V    4:      return   public java.lang.String testString(java.lang.String, java.lang.String);   Code:    0:      new #16; //class java/lang/StringBuilder    3:      dup    4:      aload_1    5:      invokestatic    #18; //Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;    8:      invokespecial  #24; //Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V    11:     aload_2    12:    invokevirtual  #27; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;    15:    invokevirtual  #31; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;    18:    areturn   public java.lang.String testStringBuffer(java.lang.StringBuffer, java.lang.String);   Code:    0:      aload_1    1:      aload_2    2:      invokevirtual  #40; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;    5:      invokevirtual  #45; //Method java/lang/StringBuffer.toString:()Ljava/lang/String;    8:      areturn }

從上面編譯后的字節(jié)碼信息可以看出來(lái),方法testString 調(diào)用了五個(gè)方法:new 、invokestatic 、invokespecial 和兩個(gè)invokevirtual ; 而testStringBuffer 方法只調(diào)用了兩個(gè)invokevirtual 方法。***個(gè)方法比第二個(gè)方法多做了好多工作,其效率當(dāng)然是要低的。而且我們從java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;

可以看出來(lái)其實(shí)對(duì)于String字符串合并,內(nèi)部還是轉(zhuǎn)化為StringBuilder的方法調(diào)用,這是因?yàn)镾tring是長(zhǎng)度不可變的,所以不如直接采用StringBuilder(與StringBuffer 長(zhǎng)度都是可變的,只不過前者是非線程安全,后者是線程安全)進(jìn)行字符串合并。

感謝各位的閱讀,以上就是“Java字節(jié)碼實(shí)例分析”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對(duì)Java字節(jié)碼實(shí)例分析這一問題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI