Javassist - 如何向方法添加行号

时间:2014-01-16 14:18:46

标签: java bytecode javassist

我是java字节码和javassist的新手。我使用javassist创建了一个新的类文件。虽然我添加了字段和方法,但我无法实现向方法添加行号。我的研究结果,我明白我需要添加linenumberattribute到方法信息的codeattribute。另外,亚麻布料由亚麻布组成。我不知道怎样才能用javassist创建一个新的linenumberattribute。

1 个答案:

答案 0 :(得分:2)

我正在编写一个生成JVM代码的编译器。我需要输出中的行号。我是这样做的。

我建立了一个与此类似的对象列表:

public class MyLineNum {
    public final short pc;
    public final short lineNum;
}

然后我添加行号表:

final ClassFile  classFile = ...;
final ConstPool  constPool = classFile.getConstPool();
final MethodInfo minfo     = new MethodInfo( ... );
final Bytecode   code      = new Bytecode( constPool );
... code that writes to 'code'

final List<MyLineNum> lineNums = new ArrayList<>();
... code that adds to 'lineNums'

final CodeAttribute codeAttr = code.toCodeAttribute();
if ( !lineNums.isEmpty() ) {
    // JVM spec describes method line number table thus:
    //    u2 line_number_table_length;
    //    { u2 start_pc;
    //      u2 line_number;
    //    } line_number_table[ line_number_table_length ];
    final int    numLineNums = lineNums.size();
    final byte[] lineNumTbl  = new byte[ ( numLineNums * 4 ) + 2 ];

    // Write line_number_table_length.
    int byteIx = 0;
    ByteArray.write16bit( numLineNums, lineNumTbl, byteIx );
    byteIx += 2;

    // Write the individual line number entries.
    for ( final MyLineNum ln : lineNums) {
        // start_pc
        ByteArray.write16bit( ln.pc, lineNumTbl, byteIx );
        byteIx += 2;
        // line_number
        ByteArray.write16bit( ln.lineNum, lineNumTbl, byteIx );
        byteIx += 2;
    }

    // Add the line number table to the CodeAttribute.
    @SuppressWarnings("unchecked")
    final List<AttributeInfo> codeAttrAttrs = codeAttr.getAttributes();
    codeAttrAttrs.removeIf( ( ai ) -> ai.getName().equals( "LineNumberTable" ) );       // remove if already present
    codeAttrAttrs.add( new AttributeInfo( constPool, "LineNumberTable", lineNumTbl ) );
}

// Attach the CodeAttribute to the MethodInfo.
minfo.setCodeAttribute( codeAttr );

// Attach the MethodInfo to the ClassFile.
try {
    classFile.addMethod( minfo );
}
catch ( final DuplicateMemberException ex ) {
    throw new AssertionError( "Caught " + ex, ex );
}