使用Javassist获取类中声明的字段的索引,以便在字节码中使用

时间:2017-01-04 04:36:48

标签: java field bytecode javassist

我想使用字节码检测来访问我已经添加到类中的整数数组字段。为此,我需要类文件中的字段索引,但我找不到它。

要更详细地解释,而不是(期望的是一个声明的本地整数,其索引I' ve从本地变量表中获取):

desired = Server.rand.nextInt(4);

我想这样做:

desired = _MyField[Server.rand.nextInt(_MyField.length)];

在JASM中:

// field reference to later access an index in the array
aload <local variable index of "this"> (push reference of class)
getfield <fieldindex> (pop reference, push field reference to stack)

// rand is a public static field in class Server
getstatic java.util.Random com.wurmonline.server.Server.rand

// field reference to pass to arraylength and the Random.nextInt(int) call
aload <local variable index of "this">
getfield <fieldindex> (push reference of array)

arraylength (pop reference, push array.length value)
invokevirtual int java.util.Random.nextInt(int) (pop length for rng, push index)
iaload (pop index, push integer value from array index)
istore <index of local variable "desired"> (pop value, store in variable)

使用Javassist添加字段,sb是包含字段初始化程序的StringBuilder(例如&#34; new int [] {n,n,n,n,n};&#34;):

ctClass.addField(
    new CtField(
            HookManager.getInstance().getClassPool().get("[I"),
            "_OtherServerMissions", 
            ctClass),
    sb.toString());

使用DirtyJOE查看一个类文件,DirtyJOE是一个与Java8 / Major类文件版本52一起使用的字节码编辑器,我找不到字段的索引值。我似乎也找不到使用CtField或适用的AttributeInfo。

for (CtField ctField : ctClass.getDeclaredFields())

所以我想知道从哪里获取fieldindex。

我希望这个解释对于熟悉此事的可怜人来说已经足够清楚了。

1 个答案:

答案 0 :(得分:0)

有时它真的有助于以某种方式向其他人解释问题。

传递给GETFIELD操作码的FIELDINDEX是对类的常量池的引用。你必须在课程中添加一个FieldrefInfo。恒定的池。 addFieldrefInfo()的返回值是常量池中的索引。

ConstPool constPool = ctClass.getClassFile().getConstPool();

[...]

sb = new StringBuilder();
sb.append("new int[] { ");
for (int i : _OtherServerMissions)
    sb.append(String.format("%d,", i));
sb.deleteCharAt(sb.lastIndexOf(","));
sb.append(" };");

ctClass.addField(
        new CtField(
                HookManager.getInstance().getClassPool().get("[I"),
                "_OtherServerMissions", 
                ctClass),
        sb.toString());

int otherFieldIndex = constPool.addFieldrefInfo(constPool.getThisClassInfo(), "_OtherServerMissions", "[I");
logger.log(Level.INFO, "Added OtherFieldIndex as " + otherFieldIndex);

在使用GETFIELD之前,您还必须确定&#34; this&#34;的索引,以便在堆栈上推送类实例的引用(如果适用)。

int thisIndex = -1;
LocalVariableAttribute lva = (LocalVariableAttribute)generateMission
    .getMethodInfo()
    .getCodeAttribute()
    .getAttribute(LocalVariableAttribute.tag);

for (int i = 0; thisIndex < 0 && i < lva.tableLength(); i++) {
    if (lva.variableName(i).equals("this"))
        thisIndex = lva.index(i);
}

如果它已经不在本地变量表中,我现在还不知道如何添加它。或者如何准确地添加到局部变量表中。如果你知道的话,请随意发表评论(如果你有足够的重复点,呃...)。

现在修复的问题包含与此处列出的值一起使用的正确java汇编代码。