Java Class文件格式解析

jopen 8年前

一、Java Class文件是什么

java语言是跨平台的,所谓一次编写,到处运行。之所以是跨平台的,就是java定义了一套与操作系统,硬件无关的字节码格式,这个字节码就是用java class文件来表示的,java class文件内部定义了虚拟机可以识别的字节码格式,这个格式是平台无关性的,在linux系统或者在windows系统上都是一致的。这个就好比html文件,我们定义好规范,这个系统只要去按照规范显示出来里面的内容就好了。好比html就是class文件,浏览器就是虚拟机一样,通过浏览器去执行html的渲染过程,我们无论是用手机,Windows系统,苹果系统上网,显示出来的内容都是一样。 java虚拟机可以从class文件中加载预定义的字节码,也可以从网络,数据库,消息文件中加载字节码。

二、Java Class文件的格式

1.多个字节的数据采用大端存储

2.class文件采用定义u1、u2、u4来表示无符号的1、2、4字节数据。

Java Class文件格式解析

简要解释一下:

U4 代表由无符号四个字节组成

u4 magic :是一个固定的数值,java虚拟机里面称为魔数 ,主要是用来标识是否为java虚拟机所支持的文件结构,目前是0xCAFEBABE

u2 minor_version; u2 major_version; 代表次版本号和主版本号

u2 constant_pool_count; cp_info constant_pool[constant_pool_count-1]; 这里面代表常量池个数以及常量池信息

u2 access_flags : 代表class访问标记,例如:public protected

u2 this_class : 代表这个类的名称 例如 java.lang.Object

u2 super_class : 代表父类名称

u2 interfaces_count; u2 interfaces[interfaces_count]; 实现的接口格式以及接口类名

u2 fields_count; field_info fields[fields_count]; 字段个数以及字段信息

u2 methods_count; method_info methods[methods_count]; 方法个数以及方法信息

u2 attributes_count; attribute_info attributes[attributes_count]; java class文件内部属性信息,和java语言定义的属性没有关系,纯粹就是给java虚拟机用的

class文件实例

/*  * Copyright (c) 2015 Javaranger.com. All Rights Reserved.  */  package com.javaranger.test;    /**   * @author tao.wang Date: 16/1/2 Time: 下午12:29   * @version $Id$   */  public class ClassTest {      public int id = 100;      private String name = "javaranger";        public void test() {          int a = 1;          int b = 2;          int c = a + b;          String str = name + ".com";          System.out.println(str);      }    }

javap -v ClassTest.class

lassfile /Users/ranger/git/transformer/src/main/java/com/javaranger/test/ClassTest.class    Last modified 2016-1-2; size 713 bytes    MD5 checksum 67738e1dedfacaa7d62444f45d8cc716    Compiled from "ClassTest.java"  public class com.javaranger.test.ClassTest    SourceFile: "ClassTest.java"    minor version: 0    major version: 51    flags: ACC_PUBLIC, ACC_SUPER  Constant pool:     #1 = Methodref          #13.#25        //  java/lang/Object."":()V     #2 = Fieldref           #12.#26        //  com/javaranger/test/ClassTest.id:I     #3 = String             #27            //  javaranger     #4 = Fieldref           #12.#28        //  com/javaranger/test/ClassTest.name:Ljava/lang/String;     #5 = Class              #29            //  java/lang/StringBuilder     #6 = Methodref          #5.#25         //  java/lang/StringBuilder."":()V     #7 = Methodref          #5.#30         //  java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;     #8 = String             #31            //  .com     #9 = Methodref          #5.#32         //  java/lang/StringBuilder.toString:()Ljava/lang/String;    #10 = Fieldref           #33.#34        //  java/lang/System.out:Ljava/io/PrintStream;    #11 = Methodref          #35.#36        //  java/io/PrintStream.println:(Ljava/lang/String;)V    #12 = Class              #37            //  com/javaranger/test/ClassTest    #13 = Class              #38            //  java/lang/Object    #14 = Utf8               id    #15 = Utf8               I    #16 = Utf8               name    #17 = Utf8               Ljava/lang/String;    #18 = Utf8    #19 = Utf8               ()V    #20 = Utf8               Code    #21 = Utf8               LineNumberTable    #22 = Utf8               test    #23 = Utf8               SourceFile    #24 = Utf8               ClassTest.java    #25 = NameAndType        #18:#19        //  "":()V    #26 = NameAndType        #14:#15        //  id:I    #27 = Utf8               javaranger    #28 = NameAndType        #16:#17        //  name:Ljava/lang/String;    #29 = Utf8               java/lang/StringBuilder    #30 = NameAndType        #39:#40        //  append:(Ljava/lang/String;)Ljava/lang/StringBuilder;    #31 = Utf8               .com    #32 = NameAndType        #41:#42        //  toString:()Ljava/lang/String;    #33 = Class              #43            //  java/lang/System    #34 = NameAndType        #44:#45        //  out:Ljava/io/PrintStream;    #35 = Class              #46            //  java/io/PrintStream    #36 = NameAndType        #47:#48        //  println:(Ljava/lang/String;)V    #37 = Utf8               com/javaranger/test/ClassTest    #38 = Utf8               java/lang/Object    #39 = Utf8               append    #40 = Utf8               (Ljava/lang/String;)Ljava/lang/StringBuilder;    #41 = Utf8               toString    #42 = Utf8               ()Ljava/lang/String;    #43 = Utf8               java/lang/System    #44 = Utf8               out    #45 = Utf8               Ljava/io/PrintStream;    #46 = Utf8               java/io/PrintStream    #47 = Utf8               println    #48 = Utf8               (Ljava/lang/String;)V  {    public int id;      flags: ACC_PUBLIC      public com.javaranger.test.ClassTest();      flags: ACC_PUBLIC      Code:        stack=2, locals=1, args_size=1           0: aload_0           1: invokespecial #1                  // Method java/lang/Object."":()V           4: aload_0           5: bipush        100           7: putfield      #2                  // Field id:I          10: aload_0          11: ldc           #3                  // String javaranger          13: putfield      #4                  // Field name:Ljava/lang/String;          16: return        LineNumberTable:          line 10: 0          line 11: 4          line 12: 10      public void test();      flags: ACC_PUBLIC      Code:        stack=2, locals=5, args_size=1           0: iconst_1           1: istore_1           2: iconst_2           3: istore_2           4: iload_1           5: iload_2           6: iadd           7: istore_3           8: new           #5                  // class java/lang/StringBuilder          11: dup          12: invokespecial #6                  // Method java/lang/StringBuilder."":()V          15: aload_0          16: getfield      #4                  // Field name:Ljava/lang/String;          19: invokevirtual #7                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;          22: ldc           #8                  // String .com          24: invokevirtual #7                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;          27: invokevirtual #9                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;          30: astore        4          32: getstatic     #10                 // Field java/lang/System.out:Ljava/io/PrintStream;          35: aload         4          37: invokevirtual #11                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V          40: return        LineNumberTable:          line 15: 0          line 16: 2          line 17: 4          line 18: 8          line 19: 32          line 20: 40  }
cafe babe 0000 0033 0031 0a00 0d00 1909  000c 001a 0800 1b09 000c 001c 0700 1d0a  0005 0019 0a00 0500 1e08 001f 0a00 0500  2009 0021 0022 0a00 2300 2407 0025 0700  2601 0002 6964 0100 0149 0100 046e 616d  6501 0012 4c6a 6176 612f 6c61 6e67 2f53  7472 696e 673b 0100 063c 696e 6974 3e01  0003 2829 5601 0004 436f 6465 0100 0f4c  696e 654e 756d 6265 7254 6162 6c65 0100  0474 6573 7401 000a 536f 7572 6365 4669  6c65 0100 0e43 6c61 7373 5465 7374 2e6a  6176 610c 0012 0013 0c00 0e00 0f01 000a  6a61 7661 7261 6e67 6572 0c00 1000 1101  0017 6a61 7661 2f6c 616e 672f 5374 7269  6e67 4275 696c 6465 720c 0027 0028 0100  042e 636f 6d0c 0029 002a 0700 2b0c 002c  002d 0700 2e0c 002f 0030 0100 1d63 6f6d  2f6a 6176 6172 616e 6765 722f 7465 7374  2f43 6c61 7373 5465 7374 0100 106a 6176  612f 6c61 6e67 2f4f 626a 6563 7401 0006  6170 7065 6e64 0100 2d28 4c6a 6176 612f  6c61 6e67 2f53 7472 696e 673b 294c 6a61  7661 2f6c 616e 672f 5374 7269 6e67 4275  696c 6465 723b 0100 0874 6f53 7472 696e  6701 0014 2829 4c6a 6176 612f 6c61 6e67  2f53 7472 696e 673b 0100 106a 6176 612f  6c61 6e67 2f53 7973 7465 6d01 0003 6f75  7401 0015 4c6a 6176 612f 696f 2f50 7269  6e74 5374 7265 616d 3b01 0013 6a61 7661  2f69 6f2f 5072 696e 7453 7472 6561 6d01  0007 7072 696e 746c 6e01 0015 284c 6a61  7661 2f6c 616e 672f 5374 7269 6e67 3b29  5600 2100 0c00 0d00 0000 0200 0100 0e00  0f00 0000 0200 1000 1100 0000 0200 0100  1200 1300 0100 1400 0000 3100 0200 0100  0000 112a b700 012a 1064 b500 022a 1203  b500 04b1 0000 0001 0015 0000 000e 0003  0000 000a 0004 000b 000a 000c 0001 0016  0013 0001 0014 0000 0055 0002 0005 0000  0029 043c 053d 1b1c 603e bb00 0559 b700  062a b400 04b6 0007 1208 b600 07b6 0009  3a04 b200 0a19 04b6 000b b100 0000 0100  1500 0000 1a00 0600 0000 0f00 0200 1000  0400 1100 0800 1200 2000 1300 2800 1400  0100 1700 0000 0200 18

来自: http://www.javaranger.com/archives/1875