Java Byte Code Constant Pool

Keywords: Java github

Introduction

The last article briefly introduced the basic format of java Class byte code files.In this paper, we will further understand the constant pool structure in byte code by reading the byte code file directly.

First let's create a new simplest Java file

public class Test {
    public static void main(String[] args) {
        System.out.println("hello world");
    }
}

After compiling, open it in a text editor and you can see the original 16-bit format of the Class file.The magic cafe babe of the most obvious Class file can be seen at a glance

cafe babe 0000 0034 0022 0a00 0600 1409
0015 0016 0800 170a 0018 0019 0700 1a07
001b 0100 063c 696e 6974 3e01 0003 2829
5601 0004 436f 6465 0100 0f4c 696e 654e
756d 6265 7254 6162 6c65 0100 124c 6f63
616c 5661 7269 6162 6c65 5461 626c 6501
0004 7468 6973 0100 144c 636f 6d2f 796d
6d2f 6167 656e 742f 5465 7374 3b01 0004
6d61 696e 0100 1628 5b4c 6a61 7661 2f6c
616e 672f 5374 7269 6e67 3b29 5601 0004
6172 6773 0100 135b 4c6a 6176 612f 6c61
6e67 2f53 7472 696e 673b 0100 0a53 6f75
7263 6546 696c 6501 0009 5465 7374 2e6a
6176 610c 0007 0008 0700 1c0c 001d 001e
0100 0b68 656c 6c6f 2077 6f72 6c64 0700
1f0c 0020 0021 0100 1263 6f6d 2f79 6d6d
2f61 6765 6e74 2f54 6573 7401 0010 6a61
7661 2f6c 616e 672f 4f62 6a65 6374 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 0500 0600 0000
0000 0200 0100 0700 0800 0100 0900 0000
2f00 0100 0100 0000 052a b700 01b1 0000
0002 000a 0000 0006 0001 0000 0009 000b
0000 000c 0001 0000 0005 000c 000d 0000
0009 000e 000f 0001 0009 0000 0037 0002
0001 0000 0009 b200 0212 03b6 0004 b100
0000 0200 0a00 0000 0a00 0200 0000 0b00
0800 0c00 0b00 0000 0c00 0100 0000 0900
1000 1100 0000 0100 1200 0000 0200 13

How do I find the location of the constant pool from the file above?

In the previous article, we analyzed the file format of the Class file. The location of the constant pool follows the version number, that is, from the ninth byte onwards. Let's take a look at the contents of the constant pool.

constant_pool_count u2

The next two bytes from the ninth byte are constant_pool_count, which we call a constant counter. Specifically, its subscript starts at 1, which means the real number of constant pools is constant_pool_count - 1. Now let's see how many constant tables (cp_info) are contained in that common Class file above.

Constant Count

You can see that the constant_pool_count identifier bit is 0022, or 34 when converted to 10.That is, 34 - 1 = 33 constant table contents

cp_info

After analysis above, we have determined the number of constants contained in the byte code file, so what do we want to see next?

Let's take a closer look at the structure of cp_info

image.png

You can see that the first byte of each cp_info is a tag, which identifies the specific type to which the constant belongs. As we said in the previous article, the constants are very complex because they have many types and 14 types.These types of distinctions are then distinguished by tags.We'll analyze each of these 14 types individually

Let's start with these 14 constant pool types

image.png

Let's go back to the 16-bit file with the byte code above and look down

image.png

You can see tag = 10, and based on the subtypes we listed above, you can determine that the first constant type that appears is constant_Methodref_info.Now let's go into the constant_Methodref_info table

constant_Methodref_info.png

You can see that immediately after the tag are two index index values, pointing to constant_Class_info and constant_NameAndType_info, respectively.

As you read further, you can see that the specific index values are 0006,0014.That is, items 6 and 20 pointing to the constant pool

For readability purposes, we use the javap-v Test command directly to generate a byte code file that is easy for us to read. Of course, if you are interested, direct reading of the source file is also oK's

public class com.ymm.agent.Test
  minor version: 0
  major version: 52
  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
  this_class: #5                          // com/ymm/agent/Test
  super_class: #6                         // java/lang/Object
  interfaces: 0, fields: 0, methods: 2, attributes: 1
Constant pool:
   #1 = Methodref          #6.#20         // java/lang/Object."<init>":()V
   #2 = Fieldref           #21.#22        // java/lang/System.out:Ljava/io/PrintStream;
   #3 = String             #23            // hello world
   #4 = Methodref          #24.#25        // java/io/PrintStream.println:(Ljava/lang/String;)V
   #5 = Class              #26            // com/ymm/agent/Test
   #6 = Class              #27            // java/lang/Object
   #7 = Utf8               <init>
   #8 = Utf8               ()V
   #9 = Utf8               Code
  #10 = Utf8               LineNumberTable
  #11 = Utf8               LocalVariableTable
  #12 = Utf8               this
  #13 = Utf8               Lcom/ymm/agent/Test;
  #14 = Utf8               main
  #15 = Utf8               ([Ljava/lang/String;)V
  #16 = Utf8               args
  #17 = Utf8               [Ljava/lang/String;
  #18 = Utf8               SourceFile
  #19 = Utf8               Test.java
  #20 = NameAndType        #7:#8          // "<init>":()V
  #21 = Class              #28            // java/lang/System
  #22 = NameAndType        #29:#30        // out:Ljava/io/PrintStream;
  #23 = Utf8               hello world
  #24 = Class              #31            // java/io/PrintStream
  #25 = NameAndType        #32:#33        // println:(Ljava/lang/String;)V
  #26 = Utf8               com/ymm/agent/Test
  #27 = Utf8               java/lang/Object
  #28 = Utf8               java/lang/System
  #29 = Utf8               out
  #30 = Utf8               Ljava/io/PrintStream;
  #31 = Utf8               java/io/PrintStream
  #32 = Utf8               println
  #33 = Utf8               (Ljava/lang/String;)V
{
  public com.ymm.agent.Test();
    descriptor: ()V
.... Omit other byte codes

The byte code file generated from javap looks much more comfortable.Now, going back to the first constant pool item constant_Methodref_info, you can see that it is made up of two index values, constant_Class_info and constant_NameAndType_info. Based on the index value 6,20, we can find the specific constant pool item content.

First find the constant_Class_info with index value 6, you can see that its specific content also points to an index value of 27, continue to look for the constant item with index value of 27

image.png

Finding a constant item with an index value of 27, you can see that it is a string of type constant_utf8_info (java/lang/Object), which is also the fully qualified name of the class we mentioned earlier

image.png

So far you should have found the feeling of reading the constant pool, so the same is true for us to look at constant_NameAndType_info with an index entry of 20

image.png

constant_NameAndType_info points to content with index values of 7 and 8

image.png

You know that the method name is init and the type is void

So far we can probably see that the first representation of this constant pool is actually a parameterless construction method and is automatically generated by the compiler for us

In fact, most complex constant pool content will eventually be indexed to a constant_utf8_info string type, which describes the fully qualified class name, method or field name, descriptor, and so on..

Endnote

This article uses only one example to read the Constant Pool content of a Class file. The specific Constant Pool structure is listed in the previous article and is read in a similar way to this one.

Blog Original Stamp Here's a look at author github

Posted by webhamster on Mon, 06 May 2019 21:15:38 -0700