Strange behaviour in .class "endianess"

Henrique M. Decaria typoon at gmail.com
Sun Oct 30 16:38:14 PDT 2011


Good evening,

I am not sure if this is the right mailing list to ask this question, but I
was unable to find a more appropriate one. If there is one, please let me
know and I will ask this question there.

I am working on parsing a .class file (decompiling it), and am facing a
problem that I cannot explain at all.
Consider the following code:

public class Ex1 {
    static public void main(String [] args) {
        int i = 99;
        long l = 20;
        System.out.println("Hi!" + i + " long = " + l);
    }
}

The compiled file of this code, when decompiled, shows a strange behaviour.
The constant pool count for this code is 50. I can populate the whole
constant pool struct without any problems. The problem starts in the bytes
that follow the constant pool. Those bytes will be in 'little endian' form
instead of big-endian. If I add one more long variable to that code, then
everything works as expected (the data after the constant pool goes back to
being big endian). I know this might sound really strange and ilogical, but
I really cannot find any explanation to that.
Here is the ClassFile struct I am using

typedef struct _ClassFile  {
    u4 magic;
    u2 minor_version;
    u2 major_version;
    u2 constant_pool_count;
    cp_info *constant_pool; //[constant_pool_count-1];
    u2 access_flags;
    u2 this_class;
    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];
} ClassFile;

And the cp_info struct

typedef struct _cp_info {
    u1 tag;
    union {
        Class_info ci;
        Fieldref_info fri;
        Methodref_info mri;
        InterfaceMethodref_info imri;
        String_info si;
        Integer_info ii;
        Float_info fi;
        Long_info li;
        Double_info di;
        NameAndType_info nti;
        Utf8_info utfi;
    };
} cp_info;

All the structs in the cp_info struct are pretty much as described here
http://java.sun.com/docs/books/jvms/second_edition/html/ClassFile.doc.html

The part of the code resposible for reading LONGs and DOUBLEs is as follows:

switch(tag) {
            case CONSTANT_LONG:
                debug(DBG_WARN, "Found long at index %d\n", index);

                fread(&tmpu4, 1, sizeof(tmpu4), f);
                cf->constant_pool[index].li.high_bytes = btoli(tmpu4);
                cf->constant_pool[index+1].li.high_bytes = btoli(tmpu4);

                fread(&tmpu4, 1, sizeof(tmpu4), f);
                cf->constant_pool[index].li.low_bytes = btoli(tmpu4);
                cf->constant_pool[index+1].li.low_bytes = btoli(tmpu4);

                ++index;
            break;

            case CONSTANT_DOUBLE:
                debug(DBG_WARN, "Found long at index %d\n", index);

                fread(&tmpu4, 1, sizeof(tmpu4), f);
                cf->constant_pool[index].di.high_bytes = btoli(tmpu4);
                cf->constant_pool[index+1].di.high_bytes = btoli(tmpu4);

                fread(&tmpu4, 1, sizeof(tmpu4), f);
                cf->constant_pool[index].di.low_bytes = btoli(tmpu4);
                cf->constant_pool[index+1].di.low_bytes = btoli(tmpu4);

                ++index;
            break;
}

The btoli function simply converts from big endian to little endian (a
swap_endian_integer name would have been more appropriate, i know).
Has anyone seem such behaviour, or have any explanation to what I could be
doing incorrectly?

Thanks a lot for your time and help :)

Henrique
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.openjdk.java.net/pipermail/compiler-dev/attachments/20111030/c0afd725/attachment.html 


More information about the compiler-dev mailing list