读取.class文件

时间:2013-08-01 02:50:23

标签: java c++ .class-file

我正在尝试学习如何使用C ++读取Java类文件。任何人都可以帮我弄清楚为什么AccessFlag打印0?它可以打印的最低值是0x00001。所以我认为我正在读取常量池表错误,但我不确定它有什么问题。有任何想法吗?我关注的是:http://www.murrayc.com/learning/java/java_classfileformat.shtml

到目前为止,我得到了:

#include <iostream>
#include <fstream>
#include <vector>

template <typename T>
T ReadPointer(char*& Pointer)
{
    T Result = *(reinterpret_cast<T*>(Pointer));
    Pointer += sizeof(T);
    return Result;
}

struct ConstantPool
{
    int type;
    std::string name;
    ConstantPool*  arg1;
    ConstantPool*  arg2;
    short index1, index2;
    std::string  strValue;
    int   intValue;
    std::int64_t  longValue;
    float floatValue;
    double  doubleValue;

    ConstantPool() {}
    ConstantPool(char* &Pointer) {this->Read(Pointer);}
    void Read(char* &Pointer);
};

void ConstantPool::Read(char* &Pointer)
{
    switch(type = static_cast<int>(ReadPointer<std::uint8_t>(Pointer)))
    {
        case 1:
        {
            name = "Ascii";
            int Length = ReadPointer<short>(Pointer);
            while (Length > 0)
            {
                char C = ReadPointer<char>(Pointer);
                strValue += C;
                Length--;
            }
        }
        break;

        case 2:
        {
            name = "Unicode";
            int Length = ReadPointer<short>(Pointer);
            while (Length > 0)
            {
                char C = ReadPointer<char>(Pointer);
                strValue += C;
                Length--;
            }
        }
        break;

        case 3:
            name = "Int";
            intValue = ReadPointer<double>(Pointer);
            break;

        case 4:
            name = "Float";
            floatValue = ReadPointer<float>(Pointer);
            break;

        case 5:
            name = "Long";
            longValue = ReadPointer<long>(Pointer);
            break;

        case 6:
            name = "Double";
            doubleValue = ReadPointer<double>(Pointer);
            break;

        case 7:
            name = "Class";
            index1 = ReadPointer<short>(Pointer);
            index2 = -1;
            break;

        case 8:
            name = "String";
            index1 = ReadPointer<short>(Pointer);
            index2 = -1;
            break;

        case 9:
            name = "Field Reference";
            index1 = ReadPointer<short>(Pointer);
            index2 = ReadPointer<short>(Pointer);
            break;

        case 10:
            name = "Method Reference";
            index1 = ReadPointer<short>(Pointer);
            index2 = ReadPointer<short>(Pointer);
            break;

        case 11:
            name = "Interface Reference";
            index1 = ReadPointer<short>(Pointer);
            index2 = ReadPointer<short>(Pointer);
            break;

        case 12:
            name = "Name And Type";
            index1 = ReadPointer<short>(Pointer);
            index2 = ReadPointer<short>(Pointer);
            break;
    }
}

typedef struct
{
    int MagicNumber;
    short MinorVersion;
    short MajorVersion;
    short ConstantPoolCount;

} ClassFile;

int main()
{
    std::fstream File("Animal.class", std::ios::in | std::ios::binary);
    if (File.is_open())
    {
        File.seekg(0, std::ios::end);
        std::vector<std::uint8_t> Data(File.tellg());
        char* Ptr = reinterpret_cast<char*>(&Data[0]);
        File.seekg(0, std::ios::beg);
        File.read(Ptr, Data.size());

        /**Check Magic Number.**/
        ClassFile BaseInfo = ReadPointer<ClassFile>(Ptr);
        if (BaseInfo.MagicNumber == 0xBEBAFECA)
        {
            std::cout << "Magic Number:    " << BaseInfo.MagicNumber << "\n";
            std::cout << "Minor Number:    " << BaseInfo.MinorVersion << "\n";
            std::cout << "Major Number:    " << BaseInfo.MajorVersion << "\n";
            std::cout << "Const Pool Size: " << BaseInfo.ConstantPoolCount << "\n";
            std::vector<ConstantPool> ConstPool;

            for (int I = 0; I < BaseInfo.ConstantPoolCount - 1; ++I)
            {
                ConstPool.push_back(ConstantPool(Ptr));
                if (ConstPool.back().type == 5 || ConstPool.back().type == 6)
                    ++I;
            }

            std::cout << "Access Flags:   " << ReadPointer<short>(Ptr);
        }

        File.close();
    }
}

1 个答案:

答案 0 :(得分:1)

一个错误是

intValue = ReadPointer<double>(Pointer);

你正在阅读一个双重而不是一个int,这会抛弃其他一切。

当然,您的代码也有很多其他问题。例如,您完全忽略了对齐和结构填充问题。