Search code examples
javaconstantspooljasmin

How to Create a Data Pool in Jasmin?


Does Jasmin have the ability to specify a constant pool? I need to be able to create a descriptor area of thousands of bytes. The area will contain arbitrary byte data including nulls. Here's an example of a typical assembly directive to declare binary constants:

data  0x00, 0x01, 10, 32 ...

Seems that Java class files contain these areas but I can't find a way in Jasmin to declare the values on such a large scale.


Solution

  • That area in the Java class file is called the Constant Pool and is described in detail in §4.4 of the JVM Spec.

    It can't, however contain arbitrary untyped data, but instead contains typed data only.

    Supported data types are:

    • CONSTANT_Class
    • CONSTANT_Fieldref
    • CONSTANT_Methodref
    • CONSTANT_InterfaceMethodref
    • CONSTANT_String
    • CONSTANT_Integer
    • CONSTANT_Float
    • CONSTANT_Long
    • CONSTANT_Double
    • CONSTANT_NameAndType
    • CONSTANT_Utf8

    None of those types support arbitrary byte data of arbitrary length. CONSTANT_Utf8 comes closest, but requires its content to be valid UTF-8 data and doesn't allow 0 bytes.

    The best way to find out how byte[] are encoded is to define one in Java and decompile the resulting .class file. As far as I know A byte[] is compiled to an initializer block setting its fields.

    Confirmed: This Java class:

    public class Test {
      byte[] b = { 0, 1, 2, 3, 100 };
    }
    

    Decompiles to this (using javac Test.java && javap -v Test):

    Compiled from "Test.java"
    public class Test extends java.lang.Object
      SourceFile: "Test.java"
      minor version: 0
      major version: 50
      Constant pool:
    const #1 = Method   #4.#13; //  java/lang/Object."<init>":()V
    const #2 = Field    #3.#14; //  Test.b:[B
    const #3 = class    #15;    //  Test
    const #4 = class    #16;    //  java/lang/Object
    const #5 = Asciz    b;
    const #6 = Asciz    [B;
    const #7 = Asciz    <init>;
    const #8 = Asciz    ()V;
    const #9 = Asciz    Code;
    const #10 = Asciz   LineNumberTable;
    const #11 = Asciz   SourceFile;
    const #12 = Asciz   Test.java;
    const #13 = NameAndType #7:#8;//  "<init>":()V
    const #14 = NameAndType #5:#6;//  b:[B
    const #15 = Asciz   Test;
    const #16 = Asciz   java/lang/Object;
    
    {
    byte[] b;
    
    public Test();
      Code:
       Stack=5, Locals=1, Args_size=1
       0:   aload_0
       1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
       4:   aload_0
       5:   iconst_5
       6:   newarray byte
       8:   dup
       9:   iconst_0
       10:  iconst_0
       11:  bastore
       12:  dup
       13:  iconst_1
       14:  iconst_1
       15:  bastore
       16:  dup
       17:  iconst_2
       18:  iconst_2
       19:  bastore
       20:  dup
       21:  iconst_3
       22:  iconst_3
       23:  bastore
       24:  dup
       25:  iconst_4
       26:  bipush  100
       28:  bastore
       29:  putfield    #2; //Field b:[B
       32:  return
      LineNumberTable: 
       line 1: 0
       line 2: 4
    
    
    }
    

    As you can see, the generated constructor "manually" sets the 5 values into the newly allocated array.