Java 创建简单类文件时,方法签名的常量池索引非法

Java 创建简单类文件时,方法签名的常量池索引非法,java,jvm,bytecode,bcel,Java,Jvm,Bytecode,Bcel,我想创建一个生成Java字节码的简单编译器。为了生成代码,我正在使用库 但是,我没有创建一个简单的类,它的main方法什么都不做。我使用以下代码(我知道它是Scala,但这并不重要,您将在后面看到)来生成类文件: private def generateClassFile(): Unit = { // JVM tutorial: https://commons.apache.org/proper/commons-bcel/manual/jvm.html val interface

我想创建一个生成Java字节码的简单编译器。为了生成代码,我正在使用库

但是,我没有创建一个简单的类,它的main方法什么都不做。我使用以下代码(我知道它是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%,并存储所有文本的名称,但我还没有弄清楚异常的情况


我期待着你的建议。谢谢你的帮助

您正在创建自己的空常量池,该池不与类关联,使用行:

val mainConstantPool: ConstantPoolGen = new ConstantPoolGen();
因此,尽管将方法签名添加到常量池中,但它不起作用,因为常量池从未添加到类文件中

首先创建常量池并将其作为最后一个参数传递给
ClassGen
构造函数,或者从
classFactory.getConstantPool()初始化
mainConstantPool