美文网首页web后端
查看java字节码文件

查看java字节码文件

作者: 测试你个头 | 来源:发表于2017-02-05 15:32 被阅读1225次

    背景:java的源码文件如果需要在jvm上运行,是需要经过编译的,编译的作用就是将.java文件转换为.class文件,.class文件便是字节码文件

    首先,字节码文件是二进制文件,所以,我们所谓的查看字节码文件,就是对其进行反向解析,将其解释为人类可以理解的类自然语言以供查看

    1.通过常用文本编辑器打开字节码文件,展示的是基本是乱码
    vim:


    2.通过IDE打开字节码文件,展示的是反编译后的内容(源代码),和实际的源代码有稍许区别,见下图对比:
    intellij idea:

    反编译后的字节码文件 源码

    字节码文件去除了注释,除此之外,代码做了些优化,比如变量定义的赋值处有些变化

    // 源码
    private Integer smtpPort = 25;
    
    // 编译后
    private Integer smtpPort = Integer.valueOf(25);
    

    方法内的代码块也做了些优化

    // 源码
    public void sendTextMail(MailContent mailContent) {
            if(null != mailContent.getToNames() && mailContent.getToNames().size() >= 1) {
                this.authenticator = new Authenticator() {
                    protected PasswordAuthentication getPasswordAuthentication() {
                        return new PasswordAuthentication(MailClient.this.username, MailClient.this.password);
                    }
                };
                this.session = Session.getInstance(this.props, this.authenticator);
                MimeMessage message = null;
    
                try {
                    message = new MimeMessage(this.session);
                    message.setFrom(new InternetAddress(mailContent.getMailFrom()));
                    message.setRecipient(RecipientType.TO, new InternetAddress(mailContent.getToNamesString()));
                    message.setSubject(mailContent.getTitle());
                    message.setText(mailContent.getMailBody());
                    message.setSentDate(new Date());
                    message.saveChanges();
                } catch (MessagingException var4) {
                    var4.printStackTrace();
                }
    
                this.sendMail(message);
            }
        }
    
    // 编译后
    public void sendTextMail(MailContent mailContent) {
    
            // check mail data
            if (null == mailContent.getToNames() || mailContent.getToNames().size() < 1) {
                return;
            }
    
            authenticator = new Authenticator() {
                @Override
                protected PasswordAuthentication getPasswordAuthentication() {
                    return new PasswordAuthentication(username, password);
                }
            };
    
            this.session = Session.getInstance(props, authenticator);
    
            MimeMessage message = null;
            try {
                message = new MimeMessage(session);
                message.setFrom(new InternetAddress(mailContent.getMailFrom()));
                message.setRecipient(Message.RecipientType.TO, new InternetAddress(mailContent.getToNamesString()));
                message.setSubject(mailContent.getTitle());
    
                message.setText(mailContent.getMailBody()); //pure text mail todo
                message.setSentDate(new Date());//send mail time
                message.saveChanges();//save mail setting
            } catch (MessagingException e) {
                e.printStackTrace();
            }
    
            this.sendMail(message);
        }
    

    3.通过java反编译工具javap查看字节码文件

    内容如下:

    Classfile /Users/kisrosen/05_PrivateProject/MailContent.class
      Last modified 2017-2-3; size 2196 bytes
      MD5 checksum d58da5b7eb14cacb8456ec74b829c9ae
      Compiled from "MailContent.java"
    public class com.wow.mailutils.MailContent
      minor version: 0
      major version: 52
      flags: ACC_PUBLIC, ACC_SUPER
    Constant pool:
       #1 = Methodref          #17.#60        // java/lang/Object."<init>":()V
       #2 = Fieldref           #16.#61        // com/wow/mailutils/MailContent.title:Ljava/lang/String;
       #3 = Fieldref           #16.#62        // com/wow/mailutils/MailContent.toNames:Ljava/util/List;
       #4 = Fieldref           #16.#63        // com/wow/mailutils/MailContent.ccNames:Ljava/util/List;
       #5 = Fieldref           #16.#64        // com/wow/mailutils/MailContent.mailFrom:Ljava/lang/String;
       #6 = Fieldref           #16.#65        // com/wow/mailutils/MailContent.mailBody:Ljava/lang/String;
       #7 = Class              #66            // java/lang/StringBuilder
       #8 = Methodref          #7.#60         // java/lang/StringBuilder."<init>":()V
       #9 = InterfaceMethodref #67.#68        // java/util/List.iterator:()Ljava/util/Iterator;
      #10 = InterfaceMethodref #69.#70        // java/util/Iterator.hasNext:()Z
      #11 = InterfaceMethodref #69.#71        // java/util/Iterator.next:()Ljava/lang/Object;
      #12 = Class              #72            // java/lang/String
      #13 = Methodref          #7.#73         // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      #14 = String             #74            // ,
      #15 = Methodref          #7.#75         // java/lang/StringBuilder.toString:()Ljava/lang/String;
      #16 = Class              #76            // com/wow/mailutils/MailContent
      #17 = Class              #77            // java/lang/Object
      #18 = Utf8               title
      #19 = Utf8               Ljava/lang/String;
      #20 = Utf8               toNames
      #21 = Utf8               Ljava/util/List;
      #22 = Utf8               Signature
      #23 = Utf8               Ljava/util/List<Ljava/lang/String;>;
      #24 = Utf8               ccNames
      #25 = Utf8               mailFrom
      #26 = Utf8               mailBody
      #27 = Utf8               <init>
      #28 = Utf8               ()V
      #29 = Utf8               Code
      #30 = Utf8               LineNumberTable
      #31 = Utf8               LocalVariableTable
      #32 = Utf8               this
      #33 = Utf8               Lcom/wow/mailutils/MailContent;
      #34 = Utf8               getTitle
      #35 = Utf8               ()Ljava/lang/String;
      #36 = Utf8               setTitle
      #37 = Utf8               (Ljava/lang/String;)V
      #38 = Utf8               getToNames
      #39 = Utf8               ()Ljava/util/List;
      #40 = Utf8               ()Ljava/util/List<Ljava/lang/String;>;
      #41 = Utf8               setToNames
      #42 = Utf8               (Ljava/util/List;)V
      #43 = Utf8               LocalVariableTypeTable
      #44 = Utf8               (Ljava/util/List<Ljava/lang/String;>;)V
      #45 = Utf8               getCcNames
      #46 = Utf8               setCcNames
      #47 = Utf8               getMailFrom
      #48 = Utf8               setMailFrom
      #49 = Utf8               getMailBody
      #50 = Utf8               setMailBody
      #51 = Utf8               getToNamesString
      #52 = Utf8               toName
      #53 = Utf8               toNameString
      #54 = Utf8               Ljava/lang/StringBuilder;
      #55 = Utf8               StackMapTable
      #56 = Class              #66            // java/lang/StringBuilder
      #57 = Class              #78            // java/util/Iterator
      #58 = Utf8               SourceFile
      #59 = Utf8               MailContent.java
      #60 = NameAndType        #27:#28        // "<init>":()V
      #61 = NameAndType        #18:#19        // title:Ljava/lang/String;
      #62 = NameAndType        #20:#21        // toNames:Ljava/util/List;
      #63 = NameAndType        #24:#21        // ccNames:Ljava/util/List;
      #64 = NameAndType        #25:#19        // mailFrom:Ljava/lang/String;
      #65 = NameAndType        #26:#19        // mailBody:Ljava/lang/String;
      #66 = Utf8               java/lang/StringBuilder
      #67 = Class              #79            // java/util/List
      #68 = NameAndType        #80:#81        // iterator:()Ljava/util/Iterator;
      #69 = Class              #78            // java/util/Iterator
      #70 = NameAndType        #82:#83        // hasNext:()Z
      #71 = NameAndType        #84:#85        // next:()Ljava/lang/Object;
      #72 = Utf8               java/lang/String
      #73 = NameAndType        #86:#87        // append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      #74 = Utf8               ,
      #75 = NameAndType        #88:#35        // toString:()Ljava/lang/String;
      #76 = Utf8               com/wow/mailutils/MailContent
      #77 = Utf8               java/lang/Object
      #78 = Utf8               java/util/Iterator
      #79 = Utf8               java/util/List
      #80 = Utf8               iterator
      #81 = Utf8               ()Ljava/util/Iterator;
      #82 = Utf8               hasNext
      #83 = Utf8               ()Z
      #84 = Utf8               next
      #85 = Utf8               ()Ljava/lang/Object;
      #86 = Utf8               append
      #87 = Utf8               (Ljava/lang/String;)Ljava/lang/StringBuilder;
      #88 = Utf8               toString
    {
      public com.wow.mailutils.MailContent();
        descriptor: ()V
        flags: 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 8: 0
          LocalVariableTable:
            Start  Length  Slot  Name   Signature
                0       5     0  this   Lcom/wow/mailutils/MailContent;
    
      public java.lang.String getTitle();
        descriptor: ()Ljava/lang/String;
        flags: ACC_PUBLIC
        Code:
          stack=1, locals=1, args_size=1
             0: aload_0
             1: getfield      #2                  // Field title:Ljava/lang/String;
             4: areturn
          LineNumberTable:
            line 35: 0
          LocalVariableTable:
            Start  Length  Slot  Name   Signature
                0       5     0  this   Lcom/wow/mailutils/MailContent;
    
      public void setTitle(java.lang.String);
        descriptor: (Ljava/lang/String;)V
        flags: ACC_PUBLIC
        Code:
          stack=2, locals=2, args_size=2
             0: aload_0
             1: aload_1
             2: putfield      #2                  // Field title:Ljava/lang/String;
             5: return
          LineNumberTable:
            line 39: 0
            line 40: 5
          LocalVariableTable:
            Start  Length  Slot  Name   Signature
                0       6     0  this   Lcom/wow/mailutils/MailContent;
                0       6     1 title   Ljava/lang/String;
    
      public java.util.List<java.lang.String> getToNames();
        descriptor: ()Ljava/util/List;
        flags: ACC_PUBLIC
        Code:
          stack=1, locals=1, args_size=1
             0: aload_0
             1: getfield      #3                  // Field toNames:Ljava/util/List;
             4: areturn
          LineNumberTable:
            line 43: 0
          LocalVariableTable:
            Start  Length  Slot  Name   Signature
                0       5     0  this   Lcom/wow/mailutils/MailContent;
        Signature: #40                          // ()Ljava/util/List<Ljava/lang/String;>;
    
      public void setToNames(java.util.List<java.lang.String>);
        descriptor: (Ljava/util/List;)V
        flags: ACC_PUBLIC
        Code:
          stack=2, locals=2, args_size=2
             0: aload_0
             1: aload_1
             2: putfield      #3                  // Field toNames:Ljava/util/List;
             5: return
          LineNumberTable:
            line 47: 0
            line 48: 5
          LocalVariableTable:
            Start  Length  Slot  Name   Signature
                0       6     0  this   Lcom/wow/mailutils/MailContent;
                0       6     1 toNames   Ljava/util/List;
          LocalVariableTypeTable:
            Start  Length  Slot  Name   Signature
                0       6     1 toNames   Ljava/util/List<Ljava/lang/String;>;
        Signature: #44                          // (Ljava/util/List<Ljava/lang/String;>;)V
    
      public java.util.List<java.lang.String> getCcNames();
        descriptor: ()Ljava/util/List;
        flags: ACC_PUBLIC
        Code:
          stack=1, locals=1, args_size=1
             0: aload_0
             1: getfield      #4                  // Field ccNames:Ljava/util/List;
             4: areturn
          LineNumberTable:
            line 51: 0
          LocalVariableTable:
            Start  Length  Slot  Name   Signature
                0       5     0  this   Lcom/wow/mailutils/MailContent;
        Signature: #40                          // ()Ljava/util/List<Ljava/lang/String;>;
    
      public void setCcNames(java.util.List<java.lang.String>);
        descriptor: (Ljava/util/List;)V
        flags: ACC_PUBLIC
        Code:
          stack=2, locals=2, args_size=2
             0: aload_0
             1: aload_1
             2: putfield      #4                  // Field ccNames:Ljava/util/List;
             5: return
          LineNumberTable:
            line 55: 0
            line 56: 5
          LocalVariableTable:
            Start  Length  Slot  Name   Signature
                0       6     0  this   Lcom/wow/mailutils/MailContent;
                0       6     1 ccNames   Ljava/util/List;
          LocalVariableTypeTable:
            Start  Length  Slot  Name   Signature
                0       6     1 ccNames   Ljava/util/List<Ljava/lang/String;>;
        Signature: #44                          // (Ljava/util/List<Ljava/lang/String;>;)V
    
      public java.lang.String getMailFrom();
        descriptor: ()Ljava/lang/String;
        flags: ACC_PUBLIC
        Code:
          stack=1, locals=1, args_size=1
             0: aload_0
             1: getfield      #5                  // Field mailFrom:Ljava/lang/String;
             4: areturn
          LineNumberTable:
            line 59: 0
          LocalVariableTable:
            Start  Length  Slot  Name   Signature
                0       5     0  this   Lcom/wow/mailutils/MailContent;
    
      public void setMailFrom(java.lang.String);
        descriptor: (Ljava/lang/String;)V
        flags: ACC_PUBLIC
        Code:
          stack=2, locals=2, args_size=2
             0: aload_0
             1: aload_1
             2: putfield      #5                  // Field mailFrom:Ljava/lang/String;
             5: return
          LineNumberTable:
            line 63: 0
            line 64: 5
          LocalVariableTable:
            Start  Length  Slot  Name   Signature
                0       6     0  this   Lcom/wow/mailutils/MailContent;
                0       6     1 mailFrom   Ljava/lang/String;
    
      public java.lang.String getMailBody();
        descriptor: ()Ljava/lang/String;
        flags: ACC_PUBLIC
        Code:
          stack=1, locals=1, args_size=1
             0: aload_0
             1: getfield      #6                  // Field mailBody:Ljava/lang/String;
             4: areturn
          LineNumberTable:
            line 67: 0
          LocalVariableTable:
            Start  Length  Slot  Name   Signature
                0       5     0  this   Lcom/wow/mailutils/MailContent;
    
      public void setMailBody(java.lang.String);
        descriptor: (Ljava/lang/String;)V
        flags: ACC_PUBLIC
        Code:
          stack=2, locals=2, args_size=2
             0: aload_0
             1: aload_1
             2: putfield      #6                  // Field mailBody:Ljava/lang/String;
             5: return
          LineNumberTable:
            line 71: 0
            line 72: 5
          LocalVariableTable:
            Start  Length  Slot  Name   Signature
                0       6     0  this   Lcom/wow/mailutils/MailContent;
                0       6     1 mailBody   Ljava/lang/String;
    
      public java.lang.String getToNamesString();
        descriptor: ()Ljava/lang/String;
        flags: ACC_PUBLIC
        Code:
          stack=2, locals=4, args_size=1
             0: new           #7                  // class java/lang/StringBuilder
             3: dup
             4: invokespecial #8                  // Method java/lang/StringBuilder."<init>":()V
             7: astore_1
             8: aload_0
             9: getfield      #3                  // Field toNames:Ljava/util/List;
            12: invokeinterface #9,  1            // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
            17: astore_2
            18: aload_2
            19: invokeinterface #10,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
            24: ifeq          53
            27: aload_2
            28: invokeinterface #11,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
            33: checkcast     #12                 // class java/lang/String
            36: astore_3
            37: aload_1
            38: aload_3
            39: invokevirtual #13                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
            42: pop
            43: aload_1
            44: ldc           #14                 // String ,
            46: invokevirtual #13                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
            49: pop
            50: goto          18
            53: aload_1
            54: invokevirtual #15                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
            57: areturn
          LineNumberTable:
            line 76: 0
            line 78: 8
            line 80: 37
            line 81: 43
            line 82: 50
            line 84: 53
          LocalVariableTable:
            Start  Length  Slot  Name   Signature
               37      13     3 toName   Ljava/lang/String;
                0      58     0  this   Lcom/wow/mailutils/MailContent;
                8      50     1 toNameString   Ljava/lang/StringBuilder;
          StackMapTable: number_of_entries = 2
            frame_type = 253 /* append */
              offset_delta = 18
              locals = [ class java/lang/StringBuilder, class java/util/Iterator ]
            frame_type = 250 /* chop */
              offset_delta = 34
    }
    SourceFile: "MailContent.java"
    

    对应源码如下:

    // 源码
    package com.wow.mailutils;
    
    import java.util.List;
    
    /**
     * Created by kisrosen on 17/1/11.
     */
    public class MailContent {
        /**
         * Mail Title
         */
        private String title;
    
        /**
         * Mail Destination List
         */
        private List<String> toNames;
    
        /**
         * Mail Copyto List
         */
        private List<String> ccNames;
    
        /**
         * Who send the mail
         */
        private String mailFrom;
    
        /**
         * Mail Body Content
         */
        private String mailBody;
    
        public String getTitle() {
            return title;
        }
    
        public void setTitle(String title) {
            this.title = title;
        }
    
        public List<String> getToNames() {
            return toNames;
        }
    
        public void setToNames(List<String> toNames) {
            this.toNames = toNames;
        }
    
        public List<String> getCcNames() {
            return ccNames;
        }
    
        public void setCcNames(List<String> ccNames) {
            this.ccNames = ccNames;
        }
    
        public String getMailFrom() {
            return mailFrom;
        }
    
        public void setMailFrom(String mailFrom) {
            this.mailFrom = mailFrom;
        }
    
        public String getMailBody() {
            return mailBody;
        }
    
        public void setMailBody(String mailBody) {
            this.mailBody = mailBody;
        }
    
        public String getToNamesString()
        {
            StringBuilder toNameString = new StringBuilder();
    
            for (String toName : this.toNames)
            {
                toNameString.append(toName);
                toNameString.append(",");
            }
    
            return toNameString.toString();
        }
    }
    

    4.通过jclasslib查看字节码文件
    jclasslib不但是一个字节码阅读器而且还包含一个类库允许开发者读取,修改,写入Java Class文件与字节码。

    由于mac安装jclasslib需要jdk1.6,比较麻烦,我直接通过intellij idea安装jclasslib的插件:

    intellij idea的jclasslib插件

    安装插件后重启intellij idea,在idea中打开一个java文件,此时View菜单上会有show bytecode in jclasslib的菜单

    jclasslib显示内容如下(和javap工具显示的相同,只是可视化程度更高):

    相关文章

      网友评论

        本文标题:查看java字节码文件

        本文链接:https://www.haomeiwen.com/subject/ckejittx.html