1 15 16 package javassist.bytecode; 17 18 import java.io.DataInputStream ; 19 import java.io.DataOutputStream ; 20 import java.io.IOException ; 21 import java.util.List ; 22 import java.util.LinkedList ; 23 import java.util.Map ; 24 25 34 public class CodeAttribute extends AttributeInfo implements Opcode { 35 38 public static final String tag = "Code"; 39 40 42 private int maxStack; 43 private int maxLocals; 44 private ExceptionTable exceptions; 45 private LinkedList attributes; 46 47 56 public CodeAttribute(ConstPool cp, int stack, int locals, byte[] code, 57 ExceptionTable etable) 58 { 59 super(cp, tag); 60 maxStack = stack; 61 maxLocals = locals; 62 info = code; 63 exceptions = etable; 64 attributes = new LinkedList (); 65 } 66 67 76 private CodeAttribute(ConstPool cp, CodeAttribute src, Map classnames) 77 throws BadBytecode 78 { 79 super(cp, tag); 80 81 maxStack = src.getMaxStack(); 82 maxLocals = src.getMaxLocals(); 83 exceptions = src.getExceptionTable().copy(cp, classnames); 84 info = src.copyCode(cp, classnames, exceptions, this); 85 86 attributes = new LinkedList (); 87 List src_attr = src.getAttributes(); 88 int num = src_attr.size(); 89 for (int i = 0; i < num; ++i) { 90 AttributeInfo ai = (AttributeInfo)src_attr.get(i); 91 attributes.add(ai.copy(cp, classnames)); 92 } 93 } 94 95 CodeAttribute(ConstPool cp, int name_id, DataInputStream in) 96 throws IOException 97 { 98 super(cp, name_id, (byte[])null); 99 int attr_len = in.readInt(); 100 101 maxStack = in.readUnsignedShort(); 102 maxLocals = in.readUnsignedShort(); 103 104 int code_len = in.readInt(); 105 info = new byte[code_len]; 106 in.readFully(info); 107 108 exceptions = new ExceptionTable(cp, in); 109 110 attributes = new LinkedList (); 111 int num = in.readUnsignedShort(); 112 for (int i = 0; i < num; ++i) 113 attributes.add(AttributeInfo.read(cp, in)); 114 } 115 116 130 public AttributeInfo copy(ConstPool newCp, Map classnames) 131 throws RuntimeCopyException 132 { 133 try { 134 return new CodeAttribute(newCp, this, classnames); 135 } 136 catch (BadBytecode e) { 137 throw new RuntimeCopyException("bad bytecode. fatal?"); 138 } 139 } 140 141 145 public static class RuntimeCopyException extends RuntimeException { 146 149 public RuntimeCopyException(String s) { 150 super(s); 151 } 152 } 153 154 159 public int length() { 160 return 18 + info.length + exceptions.size() * 8 161 + AttributeInfo.getLength(attributes); 162 } 163 164 void write(DataOutputStream out) throws IOException { 165 out.writeShort(name); out.writeInt(length() - 6); out.writeShort(maxStack); out.writeShort(maxLocals); out.writeInt(info.length); out.write(info); exceptions.write(out); 172 out.writeShort(attributes.size()); AttributeInfo.writeAll(attributes, out); } 175 176 181 public byte[] get() { 182 throw new UnsupportedOperationException ("CodeAttribute.get()"); 183 } 184 185 190 public void set(byte[] newinfo) { 191 throw new UnsupportedOperationException ("CodeAttribute.set()"); 192 } 193 194 198 public String getDeclaringClass() { 199 ConstPool cp = getConstPool(); 200 return cp.getClassName(); 201 } 202 203 206 public int getMaxStack() { 207 return maxStack; 208 } 209 210 213 public void setMaxStack(int value) { 214 maxStack = value; 215 } 216 217 224 public int computeMaxStack() throws BadBytecode { 225 maxStack = new CodeAnalyzer(this).computeMaxStack(); 226 return maxStack; 227 } 228 229 232 public int getMaxLocals() { 233 return maxLocals; 234 } 235 236 239 public void setMaxLocals(int value) { 240 maxLocals = value; 241 } 242 243 246 public int getCodeLength() { 247 return info.length; 248 } 249 250 253 public byte[] getCode() { 254 return info; 255 } 256 257 260 void setCode(byte[] newinfo) { super.set(newinfo); } 261 262 265 public CodeIterator iterator() { 266 return new CodeIterator(this); 267 } 268 269 272 public ExceptionTable getExceptionTable() { return exceptions; } 273 274 282 public List getAttributes() { return attributes; } 283 284 291 public AttributeInfo getAttribute(String name) { 292 return AttributeInfo.lookup(attributes, name); 293 } 294 295 298 private byte[] copyCode(ConstPool destCp, Map classnames, 299 ExceptionTable etable, CodeAttribute destCa) 300 throws BadBytecode 301 { 302 int len = getCodeLength(); 303 byte[] newCode = new byte[len]; 304 305 LdcEntry ldc = copyCode(this.info, 0, len, this.getConstPool(), 306 newCode, destCp, classnames); 307 return LdcEntry.doit(newCode, ldc, etable, destCa); 308 } 309 310 private static LdcEntry copyCode(byte[] code, int beginPos, int endPos, 311 ConstPool srcCp, byte[] newcode, 312 ConstPool destCp, Map classnameMap) 313 throws BadBytecode 314 { 315 int i2, index; 316 LdcEntry ldcEntry = null; 317 318 for (int i = beginPos; i < endPos; i = i2) { 319 i2 = CodeIterator.nextOpcode(code, i); 320 byte c = code[i]; 321 newcode[i] = c; 322 switch (c & 0xff) { 323 case LDC_W : 324 case LDC2_W : 325 case GETSTATIC : 326 case PUTSTATIC : 327 case GETFIELD : 328 case PUTFIELD : 329 case INVOKEVIRTUAL : 330 case INVOKESPECIAL : 331 case INVOKESTATIC : 332 case NEW : 333 case ANEWARRAY : 334 case CHECKCAST : 335 case INSTANCEOF : 336 copyConstPoolInfo(i + 1, code, srcCp, newcode, destCp, 337 classnameMap); 338 break; 339 case LDC : 340 index = code[i + 1] & 0xff; 341 index = srcCp.copy(index, destCp, classnameMap); 342 if (index < 0x100) 343 newcode[i + 1] = (byte)index; 344 else { 345 LdcEntry ldc = new LdcEntry(); 346 ldc.where = i; 347 ldc.index = index; 348 ldc.next = ldcEntry; 349 ldcEntry = ldc; 350 } 351 break; 352 case INVOKEINTERFACE : 353 copyConstPoolInfo(i + 1, code, srcCp, newcode, destCp, 354 classnameMap); 355 newcode[i + 3] = code[i + 3]; 356 newcode[i + 4] = code[i + 4]; 357 break; 358 case MULTIANEWARRAY : 359 copyConstPoolInfo(i + 1, code, srcCp, newcode, destCp, 360 classnameMap); 361 newcode[i + 3] = code[i + 3]; 362 break; 363 default : 364 while (++i < i2) 365 newcode[i] = code[i]; 366 367 break; 368 } 369 } 370 371 return ldcEntry; 372 } 373 374 private static void copyConstPoolInfo(int i, byte[] code, ConstPool srcCp, 375 byte[] newcode, ConstPool destCp, 376 Map classnameMap) { 377 int index = ((code[i] & 0xff) << 8) | (code[i + 1] & 0xff); 378 index = srcCp.copy(index, destCp, classnameMap); 379 newcode[i] = (byte)(index >> 8); 380 newcode[i + 1] = (byte)index; 381 } 382 } 383 384 final class LdcEntry { 385 LdcEntry next; 386 int where; 387 int index; 388 389 static byte[] doit(byte[] code, LdcEntry ldc, ExceptionTable etable, 390 CodeAttribute ca) 391 throws BadBytecode 392 { 393 while (ldc != null) { 394 int where = ldc.where; 395 code = CodeIterator.insertGap(code, where, 1, false, etable, ca); 396 code[where] = (byte)Opcode.LDC_W; 397 ByteArray.write16bit(ldc.index, code, where + 1); 398 ldc = ldc.next; 399 } 400 401 return code; 402 } 403 } 404 | Popular Tags |