Недопустимый постоянный индекс пула для подписи метода при создании простого файла класса

Я хочу создать простой компилятор, который генерирует байт-код Java. Для создания кода я использую библиотеку Apache BCEL.

Однако мне не удалось создать простой класс с основным методом, который ничего не делает. Я использую следующий код (я знаю, что это Scala, но это не так важно, как вы увидите позже) для создания файла класса:

private def generateClassFile(): Unit =
{
    // JVM tutorial: https://commons.apache.org/proper/commons-bcel/manual/jvm.html
    val interfaces: Array[String] = new Array(0);
    classFactory = new ClassGen(
        "MiniPascal",
        "java.lang.Object",
        null,
        Const.ACC_PUBLIC | Const.ACC_SUPER,
        interfaces
    );

    val mainConstantPool: ConstantPoolGen = new ConstantPoolGen();
    val mainMethod = generateMainMethod(mainConstantPool);
    classFactory.addMethod(mainMethod.getMethod());
}

private def generateMainMethod(mainConstantPool): MethodGen =
{
    val instructions = new InstructionList();
    instructions.append(InstructionConstants.NOP);

    mainConstantPool.addNameAndType("main", "([java/lang/String;)V");

    val methodArgumentNames = Array("args");
    val methodArgumentTypes: Array[Type] = Array(new ArrayType(Type.STRING, 1));
    val mainMethod: MethodGen = new MethodGen(
        Const.ACC_PUBLIC | Const.ACC_STATIC,
        Type.VOID,
        methodArgumentTypes,
        methodArgumentNames,
        "main", "MiniPascal",
        instructions,
        mainConstantPool
    );

    return mainMethod;
}

private def saveClassFile(): Unit =
{
    val classFile: JavaClass = classFactory.getJavaClass();
    classFile.dump("MiniPascal.class");
    //println(classFile.toString());
}

При запуске программы создается файл класса, однако при выполнении java MiniPascal я получаю следующее исключение:

java.lang.ClassFormatError: Illegal constant pool index 4 for method signature in class file MiniPascal

Я читал о байт-коде Java и знаю, что пул констант составляет около 60% содержимого файла класса и хранит имена всех литералов, но я еще не понял случай исключения.

Я с нетерпением жду ваших предложений. Спасибо за вашу помощь!


person Lukas    schedule 11.05.2017    source источник


Ответы (1)


Вы создаете свой собственный пустой постоянный пул, который вы не связываете с классом, используя строку:

val mainConstantPool: ConstantPoolGen = new ConstantPoolGen();

Таким образом, хотя вы добавляете сигнатуру метода в пул констант, это не работает, потому что пул констант никогда не добавляется в файл класса.

Либо сначала создайте пул констант и передайте его конструктору ClassGen в качестве последнего аргумента, либо инициализируйте mainConstantPool из classFactory.getConstantPool().

person Erwin Bolwidt    schedule 11.05.2017