org.sourceforge.jemm.weaver.transformation.bytecode
Class TransformSynchronized

java.lang.Object
  extended by javassist.convert.Transformer
      extended by org.sourceforge.jemm.weaver.transformation.bytecode.TransformSynchronized
All Implemented Interfaces:
javassist.bytecode.Opcode

public class TransformSynchronized
extends javassist.convert.Transformer

An implementation of a Javassist Transformer which replaces every MONITORENTER and MONITOREXIT with a call to a JEMM ShadowObject implementation beginLock/endLock method pair.

Author:
Paul Keeble

Field Summary
 
Fields inherited from interface javassist.bytecode.Opcode
AALOAD, AASTORE, ACONST_NULL, ALOAD, ALOAD_0, ALOAD_1, ALOAD_2, ALOAD_3, ANEWARRAY, ARETURN, ARRAYLENGTH, ASTORE, ASTORE_0, ASTORE_1, ASTORE_2, ASTORE_3, ATHROW, BALOAD, BASTORE, BIPUSH, CALOAD, CASTORE, CHECKCAST, D2F, D2I, D2L, DADD, DALOAD, DASTORE, DCMPG, DCMPL, DCONST_0, DCONST_1, DDIV, DLOAD, DLOAD_0, DLOAD_1, DLOAD_2, DLOAD_3, DMUL, DNEG, DREM, DRETURN, DSTORE, DSTORE_0, DSTORE_1, DSTORE_2, DSTORE_3, DSUB, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1, DUP2_X2, F2D, F2I, F2L, FADD, FALOAD, FASTORE, FCMPG, FCMPL, FCONST_0, FCONST_1, FCONST_2, FDIV, FLOAD, FLOAD_0, FLOAD_1, FLOAD_2, FLOAD_3, FMUL, FNEG, FREM, FRETURN, FSTORE, FSTORE_0, FSTORE_1, FSTORE_2, FSTORE_3, FSUB, GETFIELD, GETSTATIC, GOTO, GOTO_W, I2B, I2C, I2D, I2F, I2L, I2S, IADD, IALOAD, IAND, IASTORE, ICONST_0, ICONST_1, ICONST_2, ICONST_3, ICONST_4, ICONST_5, ICONST_M1, IDIV, IF_ACMPEQ, IF_ACMPNE, IF_ICMPEQ, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ICMPLT, IF_ICMPNE, IFEQ, IFGE, IFGT, IFLE, IFLT, IFNE, IFNONNULL, IFNULL, IINC, ILOAD, ILOAD_0, ILOAD_1, ILOAD_2, ILOAD_3, IMUL, INEG, INSTANCEOF, INVOKEINTERFACE, INVOKESPECIAL, INVOKESTATIC, INVOKEVIRTUAL, IOR, IREM, IRETURN, ISHL, ISHR, ISTORE, ISTORE_0, ISTORE_1, ISTORE_2, ISTORE_3, ISUB, IUSHR, IXOR, JSR, JSR_W, L2D, L2F, L2I, LADD, LALOAD, LAND, LASTORE, LCMP, LCONST_0, LCONST_1, LDC, LDC_W, LDC2_W, LDIV, LLOAD, LLOAD_0, LLOAD_1, LLOAD_2, LLOAD_3, LMUL, LNEG, LOOKUPSWITCH, LOR, LREM, LRETURN, LSHL, LSHR, LSTORE, LSTORE_0, LSTORE_1, LSTORE_2, LSTORE_3, LSUB, LUSHR, LXOR, MONITORENTER, MONITOREXIT, MULTIANEWARRAY, NEW, NEWARRAY, NOP, POP, POP2, PUTFIELD, PUTSTATIC, RET, RETURN, SALOAD, SASTORE, SIPUSH, STACK_GROW, SWAP, T_BOOLEAN, T_BYTE, T_CHAR, T_DOUBLE, T_FLOAT, T_INT, T_LONG, T_SHORT, TABLESWITCH, WIDE
 
Constructor Summary
TransformSynchronized(javassist.convert.Transformer transformers)
          Creates using the instance variable with type and
 
Method Summary
 int transform(javassist.CtClass clazz, int pos, javassist.bytecode.CodeIterator it, javassist.bytecode.ConstPool cp)
          Replace the MONITORENTER and MONITOEREXIT entries using the following byte code sequence: MONITORENTER becomes: aload_0 getField jemmOIF (type ShadowObject interface) swap invokeInterface jemmOIF.beginLock(obj) MONITOREXIT is almost the same except the last line is: invokeInterface jemmOIF.endLock(obj) The MONITORENTER instruction is always proceeded with an object on the stack and there is no need to find out what the variable is, instead we simply need to ensure that the stack has at top -1 the target object for the method call (jemmOIF) and the top of the stack contains the object on which to lock.
 
Methods inherited from class javassist.convert.Transformer
clean, extraLocals, getNext, initialize, initialize
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

TransformSynchronized

public TransformSynchronized(javassist.convert.Transformer transformers)
Creates using the instance variable with type and

Parameters:
transformers - The current Transformers (can't be null)
Method Detail

transform

public int transform(javassist.CtClass clazz,
                     int pos,
                     javassist.bytecode.CodeIterator it,
                     javassist.bytecode.ConstPool cp)
              throws javassist.CannotCompileException,
                     javassist.bytecode.BadBytecode
Replace the MONITORENTER and MONITOEREXIT entries using the following byte code sequence: MONITORENTER becomes: aload_0 getField jemmOIF (type ShadowObject interface) swap invokeInterface jemmOIF.beginLock(obj) MONITOREXIT is almost the same except the last line is: invokeInterface jemmOIF.endLock(obj) The MONITORENTER instruction is always proceeded with an object on the stack and there is no need to find out what the variable is, instead we simply need to ensure that the stack has at top -1 the target object for the method call (jemmOIF) and the top of the stack contains the object on which to lock. This behaviour is achieved by using the swap instruction which turns the stack from [OBJ,jemmOIF] into [jemmOIF, OBJ] where the OBJ is already on the stack before we do the transformation from the existing code. This mechanism does not match how the Sun JVM compiles the code as it does it in order. IE for synchronized(this) the following sequence is used: aload_0 - this for getting jemmOIF field getField jemmOIF aload_0 - The object to lock on invokeInterface jemmOIF.beginLock(obj) The difference likely makes no difference, both are valid. Using SWAP has the advantage of working with any code and only replaces the MONITORENTER and MONITOREXIT. Also note that this code does not change the exceptionhandler tables. They are already generated correctly to ensure MONITOREXIT is called when an exception is thrown by the Sun compiler and this is required of any java compiler so just the bytecode for MONITOREXIT itself is replaced where ever it appears.

Specified by:
transform in class javassist.convert.Transformer
Throws:
javassist.CannotCompileException
javassist.bytecode.BadBytecode


Copyright © 2009. All Rights Reserved.