1 30 package org.objectweb.asm; 31 32 import java.io.IOException ; 33 import java.io.InputStream ; 34 import java.io.PrintWriter ; 35 import java.io.StringWriter ; 36 import java.lang.instrument.ClassFileTransformer ; 37 import java.lang.instrument.IllegalClassFormatException ; 38 import java.lang.instrument.Instrumentation ; 39 import java.security.ProtectionDomain ; 40 41 import org.objectweb.asm.util.TraceClassVisitor; 42 43 import junit.framework.TestSuite; 44 45 50 public class ClassWriterComputeFramesTest extends AbstractTest { 51 52 public static void premain( 53 final String agentArgs, 54 final Instrumentation inst) 55 { 56 inst.addTransformer(new ClassFileTransformer () { 57 public byte[] transform( 58 final ClassLoader loader, 59 final String className, 60 final Class classBeingRedefined, 61 final ProtectionDomain domain, 62 final byte[] classFileBuffer) 63 throws IllegalClassFormatException 64 { 65 String n = className.replace('/', '.'); 66 if (n.indexOf("junit") != -1) { 67 return null; 68 } 69 if (agentArgs.length() == 0 || n.indexOf(agentArgs) != -1) { 70 return transformClass(n, classFileBuffer); 71 } else { 72 return null; 73 } 74 } 75 }); 76 } 77 78 private static byte[] transformClass(final String n, final byte[] clazz) { 79 ClassReader cr = new ClassReader(clazz); 80 ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES) { 81 protected String getCommonSuperClass( 82 final String type1, 83 final String type2) 84 { 85 if (n.equals("pkg.Frames")) { 86 return super.getCommonSuperClass(type1, type2); 87 } 88 ClassInfo c, d; 89 try { 90 c = new ClassInfo(type1, getClass().getClassLoader()); 91 d = new ClassInfo(type2, getClass().getClassLoader()); 92 } catch (Throwable e) { 93 throw new RuntimeException (e); 94 } 95 if (c.isAssignableFrom(d)) { 96 return type1; 97 } 98 if (d.isAssignableFrom(c)) { 99 return type2; 100 } 101 if (c.isInterface() || d.isInterface()) { 102 return "java/lang/Object"; 103 } else { 104 do { 105 c = c.getSuperclass(); 106 } while (!c.isAssignableFrom(d)); 107 return c.getType().getInternalName(); 108 } 109 } 110 }; 111 cr.accept(new ClassAdapter(cw) { 112 113 public void visit( 114 final int version, 115 final int access, 116 final String name, 117 final String signature, 118 final String superName, 119 final String [] interfaces) 120 { 121 super.visit(Opcodes.V1_6, 122 access, 123 name, 124 signature, 125 superName, 126 interfaces); 127 } 128 129 }, ClassReader.SKIP_FRAMES); 130 return cw.toByteArray(); 131 } 132 133 public static TestSuite suite() throws Exception { 134 return new ClassWriterComputeFramesTest().getSuite(); 135 } 136 137 public void test() throws Exception { 138 try { 139 Class.forName(n, true, getClass().getClassLoader()); 140 } catch (NoClassDefFoundError ncdfe) { 141 } catch (UnsatisfiedLinkError ule) { 143 } catch (ClassFormatError cfe) { 145 fail(cfe.getMessage()); 146 } catch (VerifyError ve) { 147 String s = n.replace('.', '/') + ".class"; 148 InputStream is = getClass().getClassLoader().getResourceAsStream(s); 149 ClassReader cr = new ClassReader(is); 150 byte[] b = transformClass("", cr.b); 151 StringWriter sw1 = new StringWriter (); 152 StringWriter sw2 = new StringWriter (); 153 sw2.write(ve.toString() + "\n"); 154 ClassVisitor cv1 = new TraceClassVisitor(new PrintWriter (sw1)); 155 ClassVisitor cv2 = new TraceClassVisitor(new PrintWriter (sw2)); 156 cr.accept(cv1, 0); 157 new ClassReader(b).accept(cv2, 0); 158 String s1 = sw1.toString(); 159 String s2 = sw2.toString(); 160 assertEquals("different data", s1, s2); 161 } 162 } 163 } 164 165 168 class ClassInfo { 169 170 private Type type; 171 172 private ClassLoader loader; 173 174 int access; 175 176 String superClass; 177 178 String [] interfaces; 179 180 public ClassInfo(final String type, final ClassLoader loader) { 181 this.loader = loader; 182 this.type = Type.getObjectType(type); 183 String s = type.replace('.', '/') + ".class"; 184 InputStream is = null; 185 ClassReader cr; 186 try { 187 is = loader.getResourceAsStream(s); 188 cr = new ClassReader(is); 189 } catch (IOException e) { 190 throw new RuntimeException (e); 191 } finally { 192 if (is != null) { 193 try { 194 is.close(); 195 } catch (Exception e) { 196 } 197 } 198 } 199 200 int h = cr.header; 202 ClassInfo.this.access = cr.readUnsignedShort(h); 203 char[] buf = new char[2048]; 204 206 int v = cr.getItem(cr.readUnsignedShort(h + 4)); 207 ClassInfo.this.superClass = v == 0 ? null : cr.readUTF8(v, buf); 208 ClassInfo.this.interfaces = new String [cr.readUnsignedShort(h + 6)]; 209 h += 8; 210 for (int i = 0; i < interfaces.length; ++i) { 211 interfaces[i] = cr.readClass(h, buf); 212 h += 2; 213 } 214 } 215 216 String getName() { 217 return type.getInternalName(); 218 } 219 220 Type getType() { 221 return type; 222 } 223 224 int getModifiers() { 225 return access; 226 } 227 228 ClassInfo getSuperclass() { 229 if (superClass == null) { 230 return null; 231 } 232 return new ClassInfo(superClass, loader); 233 } 234 235 ClassInfo[] getInterfaces() { 236 if (interfaces == null) { 237 return new ClassInfo[0]; 238 } 239 ClassInfo[] result = new ClassInfo[interfaces.length]; 240 for (int i = 0; i < result.length; ++i) { 241 result[i] = new ClassInfo(interfaces[i], loader); 242 } 243 return result; 244 } 245 246 boolean isInterface() { 247 return (getModifiers() & Opcodes.ACC_INTERFACE) > 0; 248 } 249 250 private boolean implementsInterface(final ClassInfo that) { 251 for (ClassInfo c = this; c != null; c = c.getSuperclass()) { 252 ClassInfo[] tis = c.getInterfaces(); 253 for (int i = 0; i < tis.length; ++i) { 254 ClassInfo ti = tis[i]; 255 if (ti.type.equals(that.type) || ti.implementsInterface(that)) { 256 return true; 257 } 258 } 259 } 260 return false; 261 } 262 263 private boolean isSubclassOf(final ClassInfo that) { 264 for (ClassInfo c = this; c != null; c = c.getSuperclass()) { 265 if (c.getSuperclass() != null 266 && c.getSuperclass().type.equals(that.type)) 267 { 268 return true; 269 } 270 } 271 return false; 272 } 273 274 public boolean isAssignableFrom(final ClassInfo that) { 275 if (this == that) { 276 return true; 277 } 278 279 if (that.isSubclassOf(this)) { 280 return true; 281 } 282 283 if (that.implementsInterface(this)) { 284 return true; 285 } 286 287 if (that.isInterface() 288 && getType().getDescriptor().equals("Ljava/lang/Object;")) 289 { 290 return true; 291 } 292 293 return false; 294 } 295 } 296 | Popular Tags |