1 29 30 package com.caucho.bytecode; 31 32 import com.caucho.log.Log; 33 import com.caucho.util.CharBuffer; 34 import com.caucho.util.L10N; 35 36 import java.io.IOException ; 37 import java.io.InputStream ; 38 import java.util.ArrayList ; 39 import java.util.logging.Logger ; 40 41 44 public class ByteCodeParser { 45 private static final Logger log = Log.open(ByteCode.class); 46 private static final L10N L = new L10N(ByteCode.class); 47 48 static final int CP_CLASS = 7; 49 static final int CP_FIELD_REF = 9; 50 static final int CP_METHOD_REF = 10; 51 static final int CP_INTERFACE_METHOD_REF = 11; 52 static final int CP_STRING = 8; 53 static final int CP_INTEGER = 3; 54 static final int CP_FLOAT = 4; 55 static final int CP_LONG = 5; 56 static final int CP_DOUBLE = 6; 57 static final int CP_NAME_AND_TYPE = 12; 58 static final int CP_UTF8 = 1; 59 60 private JavaClassLoader _loader; 61 private InputStream _is; 62 private JavaClass _class; 63 private ConstantPool _cp; 64 65 68 public void setClassLoader(JavaClassLoader loader) 69 { 70 _loader = loader; 71 } 72 73 76 public void setJavaClass(JavaClass javaClass) 77 { 78 _class = javaClass; 79 } 80 81 84 public JavaClass parse(InputStream is) 85 throws IOException 86 { 87 _is = is; 88 89 if (_loader == null) 90 _loader = new JavaClassLoader(); 91 92 if (_class == null) 93 _class = new JavaClass(_loader); 94 95 _cp = _class.getConstantPool(); 96 97 parseClass(); 98 99 return _class; 100 } 101 102 105 public ConstantPool getConstantPool() 106 { 107 return _cp; 108 } 109 110 113 public String getUTF8(int index) 114 { 115 return getConstantPool().getUtf8AsString(index); 116 } 117 118 121 private void parseClass() 122 throws IOException 123 { 124 int magic = readInt(); 125 126 if (magic != JavaClass.MAGIC) 127 throw error(L.l("bad magic number in class file")); 128 129 int minor = readShort(); 130 int major = readShort(); 131 132 _class.setMajor(major); 133 _class.setMinor(minor); 134 135 parseConstantPool(); 136 137 int accessFlags = readShort(); 138 _class.setAccessFlags(accessFlags); 139 140 int thisClassIndex = readShort(); 141 _class.setThisClass(_cp.getClass(thisClassIndex).getName()); 142 143 int superClassIndex = readShort(); 144 if (superClassIndex > 0) 145 _class.setSuperClass(_cp.getClass(superClassIndex).getName()); 146 147 int interfaceCount = readShort(); 148 for (int i = 0; i < interfaceCount; i++) { 149 int classIndex = readShort(); 150 151 _class.addInterface(_cp.getClass(classIndex).getName()); 152 } 153 154 int fieldCount = readShort(); 155 for (int i = 0; i < fieldCount; i++) { 156 parseField(); 157 } 158 159 int methodCount = readShort(); 160 for (int i = 0; i < methodCount; i++) 161 parseMethod(); 162 163 int attrCount = readShort(); 164 for (int i = 0; i < attrCount; i++) { 165 Attribute attr = parseAttribute(); 166 167 _class.addAttribute(attr); 168 } 169 } 170 171 174 public void parseConstantPool() 175 throws IOException 176 { 177 int count = readShort(); 178 179 for (int i = 1; i < count; i++) { 180 ConstantPoolEntry entry = parseConstantPoolEntry(i); 181 182 _cp.addConstant(entry); 183 184 if (entry instanceof DoubleConstant || 185 entry instanceof LongConstant) { 186 i++; 187 _cp.addConstant(null); 188 } 189 } 190 } 191 192 195 private ConstantPoolEntry parseConstantPoolEntry(int index) 196 throws IOException 197 { 198 int tag = read(); 199 200 switch (tag) { 201 case CP_CLASS: 202 return parseClassConstant(index); 203 204 case CP_FIELD_REF: 205 return parseFieldRefConstant(index); 206 207 case CP_METHOD_REF: 208 return parseMethodRefConstant(index); 209 210 case CP_INTERFACE_METHOD_REF: 211 return parseInterfaceMethodRefConstant(index); 212 213 case CP_STRING: 214 return parseStringConstant(index); 215 216 case CP_INTEGER: 217 return parseIntegerConstant(index); 218 219 case CP_FLOAT: 220 return parseFloatConstant(index); 221 222 case CP_LONG: 223 return parseLongConstant(index); 224 225 case CP_DOUBLE: 226 return parseDoubleConstant(index); 227 228 case CP_NAME_AND_TYPE: 229 return parseNameAndTypeConstant(index); 230 231 case CP_UTF8: 232 return parseUtf8Constant(index); 233 234 default: 235 throw error(L.l("'{0}' is an unknown constant pool type.", 236 tag)); 237 } 238 } 239 240 243 private ClassConstant parseClassConstant(int index) 244 throws IOException 245 { 246 int nameIndex = readShort(); 247 248 return new ClassConstant(_class.getConstantPool(), index, nameIndex); 249 } 250 251 254 private FieldRefConstant parseFieldRefConstant(int index) 255 throws IOException 256 { 257 int classIndex = readShort(); 258 int nameAndTypeIndex = readShort(); 259 260 return new FieldRefConstant(_class.getConstantPool(), index, 261 classIndex, nameAndTypeIndex); 262 } 263 264 267 private MethodRefConstant parseMethodRefConstant(int index) 268 throws IOException 269 { 270 int classIndex = readShort(); 271 int nameAndTypeIndex = readShort(); 272 273 return new MethodRefConstant(_class.getConstantPool(), index, 274 classIndex, nameAndTypeIndex); 275 } 276 277 280 private InterfaceMethodRefConstant parseInterfaceMethodRefConstant(int index) 281 throws IOException 282 { 283 int classIndex = readShort(); 284 int nameAndTypeIndex = readShort(); 285 286 return new InterfaceMethodRefConstant(_class.getConstantPool(), index, 287 classIndex, nameAndTypeIndex); 288 } 289 290 293 private StringConstant parseStringConstant(int index) 294 throws IOException 295 { 296 int stringIndex = readShort(); 297 298 return new StringConstant(_class.getConstantPool(), index, stringIndex); 299 } 300 301 304 private IntegerConstant parseIntegerConstant(int index) 305 throws IOException 306 { 307 int value = readInt(); 308 309 return new IntegerConstant(_class.getConstantPool(), index, value); 310 } 311 312 315 private FloatConstant parseFloatConstant(int index) 316 throws IOException 317 { 318 int bits = readInt(); 319 320 float value = Float.intBitsToFloat(bits); 321 322 return new FloatConstant(_class.getConstantPool(), index, value); 323 } 324 325 328 private LongConstant parseLongConstant(int index) 329 throws IOException 330 { 331 long value = readLong(); 332 333 return new LongConstant(_class.getConstantPool(), index, value); 334 } 335 336 339 private DoubleConstant parseDoubleConstant(int index) 340 throws IOException 341 { 342 long bits = readLong(); 343 344 double value = Double.longBitsToDouble(bits); 345 346 return new DoubleConstant(_class.getConstantPool(), index, value); 347 } 348 349 352 private NameAndTypeConstant parseNameAndTypeConstant(int index) 353 throws IOException 354 { 355 int nameIndex = readShort(); 356 int descriptorIndex = readShort(); 357 358 return new NameAndTypeConstant(_class.getConstantPool(), index, 359 nameIndex, descriptorIndex); 360 } 361 362 365 private Utf8Constant parseUtf8Constant(int index) 366 throws IOException 367 { 368 int length = readShort(); 369 370 CharBuffer cb = CharBuffer.allocate(); 371 372 for (int i = 0; i < length; i++) { 373 int ch = read(); 374 375 if (ch < 0x80) { 376 cb.append((char) ch); 377 } 378 else if ((ch & 0xe0) == 0xc0) { 379 int ch2 = read(); 380 i++; 381 382 cb.append((char) (((ch & 0x1f) << 6)+ 383 (ch2 & 0x3f))); 384 } 385 else { 386 int ch2 = read(); 387 int ch3 = read(); 388 i += 2; 389 390 cb.append((char) (((ch & 0xf) << 12)+ 391 ((ch2 & 0x3f) << 6) + 392 ((ch3 & 0x3f)))); 393 } 394 } 395 396 return new Utf8Constant(_class.getConstantPool(), index, cb.close()); 397 } 398 399 402 private void parseField() 403 throws IOException 404 { 405 int accessFlags = readShort(); 406 int nameIndex = readShort(); 407 int descriptorIndex = readShort(); 408 409 JavaField field = new JavaField(); 410 field.setJavaClass(_class); 411 field.setName(_cp.getUtf8(nameIndex).getValue()); 412 field.setDescriptor(_cp.getUtf8(descriptorIndex).getValue()); 413 field.setAccessFlags(accessFlags); 414 415 int attributesCount = readShort(); 416 417 for (int i = 0; i < attributesCount; i++) { 418 Attribute attr = parseAttribute(); 419 420 field.addAttribute(attr); 421 } 422 423 _class.addField(field); 424 } 425 426 429 private void parseMethod() 430 throws IOException 431 { 432 int accessFlags = readShort(); 433 int nameIndex = readShort(); 434 int descriptorIndex = readShort(); 435 436 JavaMethod method = new JavaMethod(_loader); 437 method.setJavaClass(_class); 438 method.setName(_cp.getUtf8(nameIndex).getValue()); 439 method.setDescriptor(_cp.getUtf8(descriptorIndex).getValue()); 440 method.setAccessFlags(accessFlags); 441 442 int attributesCount = readShort(); 443 444 for (int i = 0; i < attributesCount; i++) { 445 Attribute attr = parseAttribute(); 446 447 method.addAttribute(attr); 448 449 if (attr instanceof ExceptionsAttribute) { 450 ExceptionsAttribute exn = (ExceptionsAttribute) attr; 451 452 ArrayList <String > exnNames = exn.getExceptionList(); 453 454 if (exnNames.size() > 0) { 455 JClass []exnClasses = new JClass[exnNames.size()]; 456 457 for (int j = 0; j < exnNames.size(); j++) { 458 String exnName = exnNames.get(j).replace('/', '.'); 459 460 exnClasses[j] = _loader.forName(exnName); 461 } 462 463 method.setExceptionTypes(exnClasses); 464 } 465 } 466 } 467 468 _class.addMethod(method); 469 } 470 471 474 Attribute parseAttribute() 475 throws IOException 476 { 477 int nameIndex = readShort(); 478 479 String name = _cp.getUtf8(nameIndex).getValue(); 480 481 if (name.equals("Code")) { 482 CodeAttribute code = new CodeAttribute(name); 483 code.read(this); 484 return code; 485 } 486 else if (name.equals("Exceptions")) { 487 ExceptionsAttribute code = new ExceptionsAttribute(name); 488 code.read(this); 489 return code; 490 } 491 else if (name.equals("Signature")) { 492 SignatureAttribute code = new SignatureAttribute(); 493 code.read(this); 494 return code; 495 } 496 497 OpaqueAttribute attr = new OpaqueAttribute(name); 498 499 int length = readInt(); 500 501 byte []bytes = new byte[length]; 502 503 read(bytes, 0, bytes.length); 504 505 attr.setValue(bytes); 506 507 return attr; 508 } 509 510 513 long readLong() 514 throws IOException 515 { 516 return (((long) _is.read() << 56) | 517 ((long) _is.read() << 48) | 518 ((long) _is.read() << 40) | 519 ((long) _is.read() << 32) | 520 ((long) _is.read() << 24) | 521 ((long) _is.read() << 16) | 522 ((long) _is.read() << 8) | 523 ((long) _is.read())); 524 } 525 526 529 int readInt() 530 throws IOException 531 { 532 return ((_is.read() << 24) | 533 (_is.read() << 16) | 534 (_is.read() << 8) | 535 (_is.read())); 536 } 537 538 541 int readShort() 542 throws IOException 543 { 544 int c1 = _is.read(); 545 int c2 = _is.read(); 546 547 return ((c1 << 8) | c2); 548 } 549 550 553 int read() 554 throws IOException 555 { 556 return _is.read(); 557 } 558 559 562 int read(byte []buffer, int offset, int length) 563 throws IOException 564 { 565 int readLength = 0; 566 567 while (length > 0) { 568 int sublen = _is.read(buffer, offset, length); 569 570 if (sublen < 0) 571 return readLength == 0 ? -1 : readLength; 572 573 offset += sublen; 574 length -= sublen; 575 readLength += sublen; 576 } 577 578 return readLength; 579 } 580 581 584 private IOException error(String message) 585 { 586 return new IOException (message); 587 } 588 } 589 | Popular Tags |