Note that there are some explanatory texts on larger screens.

plurals
  1. POunboxing using the ASM Java library
    primarykey
    data
    text
    <p>I'm using the ASM Java library to replace some reflection. I generate the body of this method:</p> <pre><code>void set(Object object, int fieldIndex, Object value); </code></pre> <p>With this generated method, I can set fields on an object at runtime without using reflection. It works great. However, I found it fails for primitive fields. Here is the relevant part of my set method:</p> <pre><code>for (int i = 0, n = cachedFields.length; i &lt; 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); } </code></pre> <p>This code is generating case labels for a select. It works great for objects but for primitives I get this error:</p> <blockquote> <p>Expecting to find float on stack</p> </blockquote> <p>Ok, that makes sense, I need to do the unboxing myself. I implemented the following:</p> <pre><code>for (int i = 0, n = cachedFields.length; i &lt; 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); } </code></pre> <p>I have traced through and it definitely goes into "case Type.FLOAT" for the appropriate field, however, I get this error:</p> <blockquote> <p>Expecting to find object/array on stack</p> </blockquote> <p>This is where I'm stuck. For the life of me I can't figure out why the unboxing doesn't work. The "ALOAD, 3" is putting the third parameter of the set method on the stack, which should be a Float. Any ideas?</p> <p>I found the asm-commons library has a GeneratorAdapter class that has an unbox method. However, I don't really want to include yet another JAR for something that should be so simple. I looked at the GeneratorAdapter source and it is doing something very similar. I tried to modify my code to use GeneratorAdapter, just to see if it worked, but didn't find it at all easy to convert.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload