1 5 package com.tc.object.bytecode; 6 7 import com.tc.asm.ClassAdapter; 8 import com.tc.asm.ClassVisitor; 9 import com.tc.asm.MethodAdapter; 10 import com.tc.asm.MethodVisitor; 11 import com.tc.asm.Opcodes; 12 import com.tc.asm.Type; 13 14 public class JavaUtilWeakHashMapAdapter extends ClassAdapter implements Opcodes, ClassAdapterFactory { 15 private static final String HASH_MAP_CLASS = "java/util/HashMap"; 16 private static final String WEAK_HASH_MAP_CLASS = "java/util/WeakHashMap"; 17 18 private static final int SYNTHETIC_METHOD_ACCESS = ACC_PROTECTED | ACC_SYNTHETIC; 19 20 private static final String HASH_MAP_HASH_METHOD_NAME = "hash"; 21 22 private static final String TC_HASH_METHOD_NAME = ByteCodeUtil.TC_METHOD_PREFIX + "hash"; 23 private static final String HASH_METHOD_DESCRIPTION = "(Ljava/lang/Object;)I"; 24 25 private static final String TC_EQUAL_METHOD_NAME = ByteCodeUtil.TC_METHOD_PREFIX + "equal"; 26 private static final String EQ_METHOD_DESCRIPTION = "(Ljava/lang/Object;Ljava/lang/Object;)Z"; 27 28 private static final String EQ_METHOD_NAME = "eq"; 29 30 private String hashMapHashMethodDesc = null; 31 32 public JavaUtilWeakHashMapAdapter() { 33 super(null); 34 } 35 36 private JavaUtilWeakHashMapAdapter(ClassVisitor cv, ClassLoader caller) { 37 super(cv); 38 } 39 40 public ClassAdapter create(ClassVisitor visitor, ClassLoader loader) { 41 return new JavaUtilWeakHashMapAdapter(visitor, loader); 42 } 43 44 public void visitEnd() { 45 generateSyntheticHashMethod(); 46 generateSyntheticEqualMethod(); 47 super.visitEnd(); 48 } 49 50 private void generateSyntheticHashMethod() { 51 MethodVisitor mv = super.visitMethod(SYNTHETIC_METHOD_ACCESS, TC_HASH_METHOD_NAME, HASH_METHOD_DESCRIPTION, null, 52 null); 53 mv.visitCode(); 54 mv.visitVarInsn(ALOAD, 1); 55 56 if (hashMapHashMethodDesc == null) { throw new AssertionError (); } 57 Type[] args = Type.getArgumentTypes(hashMapHashMethodDesc); 58 if (args.length != 1) { throw new AssertionError ("unexpected HashMap.hash() signature: " + hashMapHashMethodDesc); } 59 60 if (args[0].getSort() == Type.INT) { 61 mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "hashCode", "()I"); 62 } else if (!args[0].getInternalName().equals("java/lang/Object")) { throw new AssertionError ("unexpected type: " 63 + args[0]); } 64 65 mv.visitMethodInsn(INVOKESTATIC, HASH_MAP_CLASS, HASH_MAP_HASH_METHOD_NAME, hashMapHashMethodDesc); 66 mv.visitInsn(IRETURN); 67 mv.visitMaxs(0, 0); 68 mv.visitEnd(); 69 } 70 71 private void generateSyntheticEqualMethod() { 72 MethodVisitor mv = super.visitMethod(SYNTHETIC_METHOD_ACCESS, TC_EQUAL_METHOD_NAME, EQ_METHOD_DESCRIPTION, null, 73 null); 74 mv.visitCode(); 75 mv.visitVarInsn(ALOAD, 1); 76 mv.visitVarInsn(ALOAD, 2); 77 mv.visitMethodInsn(INVOKESTATIC, WEAK_HASH_MAP_CLASS, EQ_METHOD_NAME, EQ_METHOD_DESCRIPTION); 78 mv.visitInsn(IRETURN); 79 mv.visitMaxs(1, 2); 80 mv.visitEnd(); 81 } 82 83 public MethodVisitor visitMethod(int access, String name, String desc, String signature, String [] exceptions) { 84 MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions); 85 return new JavaUtilWeakHashMapMethodAdapter(mv); 86 } 87 88 private class JavaUtilWeakHashMapMethodAdapter extends MethodAdapter { 89 public JavaUtilWeakHashMapMethodAdapter(MethodVisitor mv) { 90 super(mv); 91 } 92 93 public void visitMethodInsn(int opcode, String owner, String name, String desc) { 94 if ((INVOKEVIRTUAL == opcode) && "java/lang/Object".equals(owner) && "hashCode".equals(name)) { return; } 95 96 if (INVOKESTATIC == opcode && HASH_MAP_CLASS.equals(owner) && HASH_MAP_HASH_METHOD_NAME.equals(name)) { 97 hashMapHashMethodDesc = desc; 98 ByteCodeUtil.pushThis(this); 99 super.visitInsn(SWAP); 100 super.visitMethodInsn(INVOKEVIRTUAL, WEAK_HASH_MAP_CLASS, TC_HASH_METHOD_NAME, HASH_METHOD_DESCRIPTION); 101 } else if (INVOKESTATIC == opcode && WEAK_HASH_MAP_CLASS.equals(owner) && EQ_METHOD_NAME.equals(name) 102 && EQ_METHOD_DESCRIPTION.equals(desc)) { 103 ByteCodeUtil.pushThis(mv); 104 super.visitInsn(SWAP); 105 super.visitInsn(DUP2_X1); 106 super.visitInsn(POP2); 107 super.visitInsn(SWAP); 108 super.visitMethodInsn(INVOKEVIRTUAL, WEAK_HASH_MAP_CLASS, TC_EQUAL_METHOD_NAME, desc); 109 } else { 110 super.visitMethodInsn(opcode, owner, name, desc); 111 } 112 } 113 } 114 } | Popular Tags |