KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > tc > object > bytecode > StringBufferAdapter


1 /*
2  * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright
3  * notice. All rights reserved.
4  */

5 package com.tc.object.bytecode;
6
7 import com.tc.asm.ClassAdapter;
8 import com.tc.asm.ClassVisitor;
9 import com.tc.asm.Label;
10 import com.tc.asm.MethodAdapter;
11 import com.tc.asm.MethodVisitor;
12 import com.tc.asm.Opcodes;
13 import com.tc.util.runtime.Vm.Version;
14
15 public class StringBufferAdapter extends ClassAdapter implements Opcodes {
16
17   private final Version version;
18
19   public StringBufferAdapter(ClassVisitor cv, Version version) {
20     super(cv);
21     this.version = version;
22   }
23
24   public MethodVisitor visitMethod(int access, String JavaDoc name, String JavaDoc desc, String JavaDoc signature, String JavaDoc[] exceptions) {
25     MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
26     if ("toString".equals(name) && "()Ljava/lang/String;".equals(desc) && version.isJDK14()) {
27       rewriteToString1_4(mv);
28       return null;
29     }
30
31     return mv;
32   }
33
34   private void rewriteToString1_4(MethodVisitor mv) {
35     // This code is from the String(StringBuffer) constructor. It's easier to do the autolocking here, instead of in
36
// String -- otherwise the code is exactly the same
37
mv.visitCode();
38     Label l0 = new Label();
39     mv.visitLabel(l0);
40     mv.visitLineNumber(12, l0);
41     mv.visitVarInsn(ALOAD, 0);
42     mv.visitInsn(DUP);
43     mv.visitVarInsn(ASTORE, 1);
44     mv.visitInsn(MONITORENTER);
45     Label l1 = new Label();
46     mv.visitLabel(l1);
47     mv.visitLineNumber(13, l1);
48     mv.visitVarInsn(ALOAD, 0);
49     mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuffer", "setShared", "()V");
50     Label l2 = new Label();
51     mv.visitLabel(l2);
52     mv.visitLineNumber(14, l2);
53     mv.visitTypeInsn(NEW, "java/lang/String");
54     mv.visitInsn(DUP);
55     mv.visitInsn(ICONST_0);
56     mv.visitVarInsn(ALOAD, 0);
57     mv.visitFieldInsn(GETFIELD, "java/lang/StringBuffer", "count", "I");
58     mv.visitVarInsn(ALOAD, 0);
59     mv.visitFieldInsn(GETFIELD, "java/lang/StringBuffer", "value", "[C");
60     mv.visitMethodInsn(INVOKESPECIAL, "java/lang/String", "<init>", "(II[C)V");
61     mv.visitVarInsn(ALOAD, 1);
62     mv.visitInsn(MONITOREXIT);
63     Label l3 = new Label();
64     mv.visitLabel(l3);
65     mv.visitInsn(ARETURN);
66     Label l4 = new Label();
67     mv.visitLabel(l4);
68     mv.visitLineNumber(12, l4);
69     mv.visitVarInsn(ALOAD, 1);
70     mv.visitInsn(MONITOREXIT);
71     Label l5 = new Label();
72     mv.visitLabel(l5);
73     mv.visitInsn(ATHROW);
74     Label l6 = new Label();
75     mv.visitLabel(l6);
76     mv.visitTryCatchBlock(l1, l3, l4, null);
77     mv.visitTryCatchBlock(l4, l5, l4, null);
78     mv.visitMaxs(0, 0);
79     mv.visitEnd();
80   }
81
82   public static class FixUp extends ClassAdapter {
83
84     private static final String JavaDoc MANAGED_APPEND = DuplicateMethodAdapter.MANAGED_PREFIX + "append";
85     private final Version version;
86
87     public FixUp(ClassVisitor cv, Version version) {
88       super(cv);
89       this.version = version;
90     }
91
92     public MethodVisitor visitMethod(int access, String JavaDoc name, String JavaDoc desc, String JavaDoc signature, String JavaDoc[] exceptions) {
93       MethodVisitor visitor = super.visitMethod(access, name, desc, signature, exceptions);
94
95       if (MANAGED_APPEND.equals(name) && "([CII)Ljava/lang/StringBuffer;".equals(desc) && version.isJDK14()) {
96         // comment to make formatter sane
97
return new CloneCharArrayFixup(visitor);
98       }
99
100       return visitor;
101     }
102
103     // Because the char[] argument to StringBuffer.append([CII) is potentially a threadlocal (see Long.appendTo(long,
104
// StringBuffer) in JDK1.4), we need to make a defensive copy before calling anymore code that can modify it before
105
// it gets appended into this StringBuffer. Specifically, our code to get the DSO monitor was corrupting the char[]
106
// from the ThreadLocal
107
private static class CloneCharArrayFixup extends MethodAdapter {
108       public CloneCharArrayFixup(MethodVisitor mv) {
109         super(mv);
110         mv.visitVarInsn(ALOAD, 1);
111         mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "clone", "()Ljava/lang/Object;");
112         mv.visitTypeInsn(CHECKCAST, "[C");
113         mv.visitVarInsn(ASTORE, 1);
114       }
115     }
116   }
117
118 }
119
Popular Tags