Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/329.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用ASM Java库取消装箱_Java_Bytecode_Java Bytecode Asm_Bytecode Manipulation - Fatal编程技术网

使用ASM Java库取消装箱

使用ASM Java库取消装箱,java,bytecode,java-bytecode-asm,bytecode-manipulation,Java,Bytecode,Java Bytecode Asm,Bytecode Manipulation,我正在使用ASMJava库来替换一些反射。我生成此方法的主体: void set(Object object, int fieldIndex, Object value); 使用这个生成的方法,我可以在运行时在对象上设置字段,而无需使用反射。它工作得很好。但是,我发现它对基本字段无效。以下是我的set方法的相关部分: for (int i = 0, n = cachedFields.length; i < n; i++) { mv.visitLabel(labels[i]);

我正在使用ASMJava库来替换一些反射。我生成此方法的主体:

void set(Object object, int fieldIndex, Object value);
使用这个生成的方法,我可以在运行时在对象上设置字段,而无需使用反射。它工作得很好。但是,我发现它对基本字段无效。以下是我的set方法的相关部分:

for (int i = 0, n = cachedFields.length; i < n; i++) {
    mv.visitLabel(labels[i]);
    mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
    mv.visitVarInsn(ALOAD, 1);
    mv.visitTypeInsn(CHECKCAST, targetClassName);
    mv.visitVarInsn(ALOAD, 3);
    Field field = cachedFields[i].field;
    Type fieldType = Type.getType(field.getType());
    mv.visitFieldInsn(PUTFIELD, targetClassName, field.getName(), fieldType.getDescriptor());
    mv.visitInsn(RETURN);
}
for(int i=0,n=cachedFields.length;i
此代码正在为select生成案例标签。它适用于对象,但对于基本体,我会遇到以下错误:

希望在堆栈上找到float

好的,这很有道理,我需要自己拆箱。我实施了以下措施:

for (int i = 0, n = cachedFields.length; i < n; i++) {
    mv.visitLabel(labels[i]);
    mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
    mv.visitVarInsn(ALOAD, 1);
    mv.visitTypeInsn(CHECKCAST, targetClassName);
    mv.visitVarInsn(ALOAD, 3);

    Field field = cachedFields[i].field;
    Type fieldType = Type.getType(field.getType());
    switch (fieldType.getSort()) {
    case Type.BOOLEAN:
        mv.visitTypeInsn(CHECKCAST, "java/lang/Boolean");
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z");
        break;
    case Type.BYTE:
        mv.visitTypeInsn(CHECKCAST, "java/lang/Byte");
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B");
        break;
    case Type.CHAR:
        mv.visitTypeInsn(CHECKCAST, "java/lang/Character");
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C");
        break;
    case Type.SHORT:
        mv.visitTypeInsn(CHECKCAST, "java/lang/Short");
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S");
        break;
    case Type.INT:
        mv.visitTypeInsn(CHECKCAST, "java/lang/Integer");
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I");
        break;
    case Type.FLOAT:
        mv.visitTypeInsn(CHECKCAST, "java/lang/Float");
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F");
        break;
    case Type.LONG:
        mv.visitTypeInsn(CHECKCAST, "java/lang/Long");
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J");
        break;
    case Type.DOUBLE:
        mv.visitTypeInsn(CHECKCAST, "java/lang/Double");
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D");
        break;
    case Type.ARRAY:
        mv.visitTypeInsn(CHECKCAST, fieldType.getDescriptor());
        break;
    case Type.OBJECT:
        mv.visitTypeInsn(CHECKCAST, fieldType.getInternalName());
        break;
    }

    mv.visitFieldInsn(PUTFIELD, targetClassName, field.getName(), fieldType.getDescriptor());
    mv.visitInsn(RETURN);
}
for(int i=0,n=cachedFields.length;i
我已经跟踪到,它肯定会进入相应字段的“case Type.FLOAT”,但是,我得到以下错误:

希望在堆栈上找到对象/数组

这就是我被困的地方。我一辈子都搞不懂为什么拆箱不起作用。“ALOAD,3”将set方法的第三个参数放在堆栈上,它应该是一个Float。有什么想法吗


我发现asm commons库有一个GeneratorAdapter类,它有一个unbox方法。然而,我真的不想再为一些应该如此简单的东西包括另一个罐子。我查看了GeneratorAdapter源,它正在做一些非常类似的事情。我试图修改我的代码以使用GeneratorAdapter,只是想看看它是否工作,但我发现它根本不容易转换。

结果表明,上面的取消装箱工作正常。我有一段代码,在尝试将结果作为对象返回之前,它正在执行get,而不是装箱。我的错是没有一个更简单的测试

如果其他人需要,以下是装箱的正确代码:

Type fieldType = Type.getType(...);
switch (fieldType.getSort()) {
case Type.BOOLEAN:
    mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;");
    break;
case Type.BYTE:
    mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;");
    break;
case Type.CHAR:
    mv.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;");
    break;
case Type.SHORT:
    mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;");
    break;
case Type.INT:
    mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;");
    break;
case Type.FLOAT:
    mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;");
    break;
case Type.LONG:
    mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;");
    break;
case Type.DOUBLE:
    mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;");
    break;
}

使用GeneratorAdapter必须比MethodVisitor更干净,并且有一个unbox(),用于插入正确的调用原语.valueOf()方法调用。

谢谢,但我不希望依赖于使用GeneratorAdapter所需的其他asm commons JAR。