Mercurial > hg > truffle
comparison agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ClassWriter.java @ 705:1f2abec69714
6826261: class file dumping from SA is broken
Reviewed-by: kvn, jcoomes
author | never |
---|---|
date | Fri, 03 Apr 2009 18:51:31 -0700 |
parents | a61af66fc99e |
children | bd02caa94611 |
comparison
equal
deleted
inserted
replaced
704:ad8c635e757e | 705:1f2abec69714 |
---|---|
38 } | 38 } |
39 | 39 |
40 protected InstanceKlass klass; | 40 protected InstanceKlass klass; |
41 protected DataOutputStream dos; | 41 protected DataOutputStream dos; |
42 protected ConstantPool cpool; | 42 protected ConstantPool cpool; |
43 protected boolean is15Format; | |
44 | 43 |
45 // Map between class name to index of type CONSTANT_Class | 44 // Map between class name to index of type CONSTANT_Class |
46 protected Map classToIndex = new HashMap(); | 45 protected Map classToIndex = new HashMap(); |
47 | 46 |
48 // Map between any modified UTF-8 and it's constant pool index. | 47 // Map between any modified UTF-8 and it's constant pool index. |
71 | 70 |
72 public ClassWriter(InstanceKlass kls, OutputStream os) { | 71 public ClassWriter(InstanceKlass kls, OutputStream os) { |
73 klass = kls; | 72 klass = kls; |
74 dos = new DataOutputStream(os); | 73 dos = new DataOutputStream(os); |
75 cpool = klass.getConstants(); | 74 cpool = klass.getConstants(); |
76 is15Format = is15ClassFile(); | |
77 } | 75 } |
78 | 76 |
79 public void write() throws IOException { | 77 public void write() throws IOException { |
80 if (DEBUG) debugMessage("class name = " + klass.getName().asString()); | 78 if (DEBUG) debugMessage("class name = " + klass.getName().asString()); |
81 | 79 |
82 // write magic | 80 // write magic |
83 dos.writeInt(0xCAFEBABE); | 81 dos.writeInt(0xCAFEBABE); |
84 | 82 |
85 writeVersion(is15Format); | 83 writeVersion(); |
86 writeConstantPool(); | 84 writeConstantPool(); |
87 writeClassAccessFlags(); | 85 writeClassAccessFlags(); |
88 writeThisClass(); | 86 writeThisClass(); |
89 writeSuperClass(); | 87 writeSuperClass(); |
90 writeInterfaces(); | 88 writeInterfaces(); |
94 | 92 |
95 // flush output | 93 // flush output |
96 dos.flush(); | 94 dos.flush(); |
97 } | 95 } |
98 | 96 |
99 protected boolean is15ClassFile() { | 97 protected void writeVersion() throws IOException { |
100 // if klass has generic signature, then it is 1.5 class file. | 98 dos.writeShort((short)klass.minorVersion()); |
101 if (klass.getGenericSignature() != null) { | 99 dos.writeShort((short)klass.majorVersion()); |
102 return true; | 100 } |
103 } | 101 |
104 | 102 protected void writeIndex(int index) throws IOException { |
105 // if atleast one method has generic signature | 103 if (index == 0) throw new InternalError(); |
106 // , then we have 1.5 class file. | 104 dos.writeShort(index); |
107 ObjArray methods = klass.getMethods(); | |
108 final int numMethods = (int) methods.getLength(); | |
109 for (int m = 0; m < numMethods; m++) { | |
110 Method curMethod = (Method) methods.getObjAt(m); | |
111 if (curMethod.getGenericSignature() != null) { | |
112 return true; | |
113 } | |
114 } | |
115 | |
116 // if atleast one field has non-zero generic signature index, then we have | |
117 // 1.5 class file | |
118 TypeArray fields = klass.getFields(); | |
119 final int numFields = (int) fields.getLength(); | |
120 for (int f = 0; f < numFields; f += InstanceKlass.NEXT_OFFSET) { | |
121 short genSigIndex = fields.getShortAt(f + InstanceKlass.GENERIC_SIGNATURE_INDEX_OFFSET); | |
122 if (genSigIndex != (short)0) return true; | |
123 } | |
124 | |
125 return false; | |
126 } | |
127 | |
128 protected void writeVersion(boolean is15Format) throws IOException { | |
129 if (is15Format) { | |
130 dos.writeShort(MINOR_VERSION); | |
131 dos.writeShort(MAJOR_VERSION); | |
132 } else { | |
133 dos.writeShort(MINOR_VERSION_OLD); | |
134 dos.writeShort(MAJOR_VERSION_OLD); | |
135 } | |
136 } | 105 } |
137 | 106 |
138 protected void writeConstantPool() throws IOException { | 107 protected void writeConstantPool() throws IOException { |
139 final TypeArray tags = cpool.getTags(); | 108 final TypeArray tags = cpool.getTags(); |
140 final long len = tags.getLength(); | 109 final long len = tags.getLength(); |
390 short signatureIndex = fields.getShortAt(index + InstanceKlass.SIGNATURE_INDEX_OFFSET); | 359 short signatureIndex = fields.getShortAt(index + InstanceKlass.SIGNATURE_INDEX_OFFSET); |
391 dos.writeShort(signatureIndex); | 360 dos.writeShort(signatureIndex); |
392 if (DEBUG) debugMessage("\tfield name = " + nameIndex + ", signature = " + signatureIndex); | 361 if (DEBUG) debugMessage("\tfield name = " + nameIndex + ", signature = " + signatureIndex); |
393 | 362 |
394 short fieldAttributeCount = 0; | 363 short fieldAttributeCount = 0; |
395 boolean isSyn = isSynthetic(accessFlags); | 364 boolean hasSyn = hasSyntheticAttribute(accessFlags); |
396 if (isSyn) | 365 if (hasSyn) |
397 fieldAttributeCount++; | 366 fieldAttributeCount++; |
398 | 367 |
399 short initvalIndex = fields.getShortAt(index + InstanceKlass.INITVAL_INDEX_OFFSET); | 368 short initvalIndex = fields.getShortAt(index + InstanceKlass.INITVAL_INDEX_OFFSET); |
400 if (initvalIndex != 0) | 369 if (initvalIndex != 0) |
401 fieldAttributeCount++; | 370 fieldAttributeCount++; |
405 fieldAttributeCount++; | 374 fieldAttributeCount++; |
406 | 375 |
407 dos.writeShort(fieldAttributeCount); | 376 dos.writeShort(fieldAttributeCount); |
408 | 377 |
409 // write synthetic, if applicable | 378 // write synthetic, if applicable |
410 if (isSyn) | 379 if (hasSyn) |
411 writeSynthetic(); | 380 writeSynthetic(); |
412 | 381 |
413 if (initvalIndex != 0) { | 382 if (initvalIndex != 0) { |
414 dos.writeShort(_constantValueIndex); | 383 writeIndex(_constantValueIndex); |
415 dos.writeInt(2); | 384 dos.writeInt(2); |
416 dos.writeShort(initvalIndex); | 385 dos.writeShort(initvalIndex); |
417 if (DEBUG) debugMessage("\tfield init value = " + initvalIndex); | 386 if (DEBUG) debugMessage("\tfield init value = " + initvalIndex); |
418 } | 387 } |
419 | 388 |
420 if (genSigIndex != 0) { | 389 if (genSigIndex != 0) { |
421 dos.writeShort(_signatureIndex); | 390 writeIndex(_signatureIndex); |
422 dos.writeInt(2); | 391 dos.writeInt(2); |
423 dos.writeShort(genSigIndex); | 392 dos.writeShort(genSigIndex); |
424 if (DEBUG) debugMessage("\tfield generic signature index " + genSigIndex); | 393 if (DEBUG) debugMessage("\tfield generic signature index " + genSigIndex); |
425 } | 394 } |
426 } | 395 } |
428 | 397 |
429 protected boolean isSynthetic(short accessFlags) { | 398 protected boolean isSynthetic(short accessFlags) { |
430 return (accessFlags & (short) JVM_ACC_SYNTHETIC) != 0; | 399 return (accessFlags & (short) JVM_ACC_SYNTHETIC) != 0; |
431 } | 400 } |
432 | 401 |
402 protected boolean hasSyntheticAttribute(short accessFlags) { | |
403 // Check if flags have the attribute and if the constant pool contains an entry for it. | |
404 return isSynthetic(accessFlags) && _syntheticIndex != 0; | |
405 } | |
406 | |
433 protected void writeSynthetic() throws IOException { | 407 protected void writeSynthetic() throws IOException { |
434 dos.writeShort(_syntheticIndex); | 408 writeIndex(_syntheticIndex); |
435 dos.writeInt(0); | 409 dos.writeInt(0); |
436 } | 410 } |
437 | 411 |
438 protected void writeMethods() throws IOException { | 412 protected void writeMethods() throws IOException { |
439 ObjArray methods = klass.getMethods(); | 413 ObjArray methods = klass.getMethods(); |
457 final boolean isNative = ((accessFlags & JVM_ACC_NATIVE) != 0); | 431 final boolean isNative = ((accessFlags & JVM_ACC_NATIVE) != 0); |
458 final boolean isAbstract = ((accessFlags & JVM_ACC_ABSTRACT) != 0); | 432 final boolean isAbstract = ((accessFlags & JVM_ACC_ABSTRACT) != 0); |
459 | 433 |
460 short methodAttributeCount = 0; | 434 short methodAttributeCount = 0; |
461 | 435 |
462 final boolean isSyn = isSynthetic((short)accessFlags); | 436 final boolean hasSyn = hasSyntheticAttribute((short)accessFlags); |
463 if (isSyn) | 437 if (hasSyn) |
464 methodAttributeCount++; | 438 methodAttributeCount++; |
465 | 439 |
466 final boolean hasCheckedExceptions = m.hasCheckedExceptions(); | 440 final boolean hasCheckedExceptions = m.hasCheckedExceptions(); |
467 if (hasCheckedExceptions) | 441 if (hasCheckedExceptions) |
468 methodAttributeCount++; | 442 methodAttributeCount++; |
476 methodAttributeCount++; | 450 methodAttributeCount++; |
477 | 451 |
478 dos.writeShort(methodAttributeCount); | 452 dos.writeShort(methodAttributeCount); |
479 if (DEBUG) debugMessage("\tmethod attribute count = " + methodAttributeCount); | 453 if (DEBUG) debugMessage("\tmethod attribute count = " + methodAttributeCount); |
480 | 454 |
481 if (isSyn) { | 455 if (hasSyn) { |
482 if (DEBUG) debugMessage("\tmethod is synthetic"); | 456 if (DEBUG) debugMessage("\tmethod is synthetic"); |
483 writeSynthetic(); | 457 writeSynthetic(); |
484 } | |
485 | |
486 if (hasCheckedExceptions) { | |
487 CheckedExceptionElement[] exceptions = m.getCheckedExceptions(); | |
488 dos.writeShort(_exceptionsIndex); | |
489 | |
490 int attrSize = 2 /* number_of_exceptions */ + | |
491 exceptions.length * 2 /* exception_index */; | |
492 dos.writeInt(attrSize); | |
493 dos.writeShort(exceptions.length); | |
494 if (DEBUG) debugMessage("\tmethod has " + exceptions.length | |
495 + " checked exception(s)"); | |
496 for (int e = 0; e < exceptions.length; e++) { | |
497 short cpIndex = (short) exceptions[e].getClassCPIndex(); | |
498 dos.writeShort(cpIndex); | |
499 } | |
500 } | 458 } |
501 | 459 |
502 if (isCodeAvailable) { | 460 if (isCodeAvailable) { |
503 byte[] code = m.getByteCode(); | 461 byte[] code = m.getByteCode(); |
504 short codeAttrCount = 0; | 462 short codeAttrCount = 0; |
572 // fix ConstantPoolCache indices to ConstantPool indices. | 530 // fix ConstantPoolCache indices to ConstantPool indices. |
573 rewriteByteCode(m, code); | 531 rewriteByteCode(m, code); |
574 | 532 |
575 // start writing Code | 533 // start writing Code |
576 | 534 |
577 dos.writeShort(_codeIndex); | 535 writeIndex(_codeIndex); |
578 | 536 |
579 dos.writeInt(codeSize); | 537 dos.writeInt(codeSize); |
580 if (DEBUG) debugMessage("\tcode attribute length = " + codeSize); | 538 if (DEBUG) debugMessage("\tcode attribute length = " + codeSize); |
581 | 539 |
582 dos.writeShort((short) m.getMaxStack()); | 540 dos.writeShort((short) m.getMaxStack()); |
606 dos.writeShort((short)codeAttrCount); | 564 dos.writeShort((short)codeAttrCount); |
607 if (DEBUG) debugMessage("\tcode attribute count = " + codeAttrCount); | 565 if (DEBUG) debugMessage("\tcode attribute count = " + codeAttrCount); |
608 | 566 |
609 // write LineNumberTable, if available. | 567 // write LineNumberTable, if available. |
610 if (hasLineNumberTable) { | 568 if (hasLineNumberTable) { |
611 dos.writeShort(_lineNumberTableIndex); | 569 writeIndex(_lineNumberTableIndex); |
612 dos.writeInt(lineNumberAttrLen); | 570 dos.writeInt(lineNumberAttrLen); |
613 dos.writeShort((short) lineNumberTable.length); | 571 dos.writeShort((short) lineNumberTable.length); |
614 for (int l = 0; l < lineNumberTable.length; l++) { | 572 for (int l = 0; l < lineNumberTable.length; l++) { |
615 dos.writeShort((short) lineNumberTable[l].getStartBCI()); | 573 dos.writeShort((short) lineNumberTable[l].getStartBCI()); |
616 dos.writeShort((short) lineNumberTable[l].getLineNumber()); | 574 dos.writeShort((short) lineNumberTable[l].getLineNumber()); |
617 } | 575 } |
618 } | 576 } |
619 | 577 |
620 // write LocalVariableTable, if available. | 578 // write LocalVariableTable, if available. |
621 if (hasLocalVariableTable) { | 579 if (hasLocalVariableTable) { |
622 dos.writeShort((short) _localVariableTableIndex); | 580 writeIndex((short) _localVariableTableIndex); |
623 dos.writeInt(localVarAttrLen); | 581 dos.writeInt(localVarAttrLen); |
624 dos.writeShort((short) localVariableTable.length); | 582 dos.writeShort((short) localVariableTable.length); |
625 for (int l = 0; l < localVariableTable.length; l++) { | 583 for (int l = 0; l < localVariableTable.length; l++) { |
626 dos.writeShort((short) localVariableTable[l].getStartBCI()); | 584 dos.writeShort((short) localVariableTable[l].getStartBCI()); |
627 dos.writeShort((short) localVariableTable[l].getLength()); | 585 dos.writeShort((short) localVariableTable[l].getLength()); |
630 dos.writeShort((short) localVariableTable[l].getSlot()); | 588 dos.writeShort((short) localVariableTable[l].getSlot()); |
631 } | 589 } |
632 } | 590 } |
633 } | 591 } |
634 | 592 |
593 if (hasCheckedExceptions) { | |
594 CheckedExceptionElement[] exceptions = m.getCheckedExceptions(); | |
595 writeIndex(_exceptionsIndex); | |
596 | |
597 int attrSize = 2 /* number_of_exceptions */ + | |
598 exceptions.length * 2 /* exception_index */; | |
599 dos.writeInt(attrSize); | |
600 dos.writeShort(exceptions.length); | |
601 if (DEBUG) debugMessage("\tmethod has " + exceptions.length | |
602 + " checked exception(s)"); | |
603 for (int e = 0; e < exceptions.length; e++) { | |
604 short cpIndex = (short) exceptions[e].getClassCPIndex(); | |
605 dos.writeShort(cpIndex); | |
606 } | |
607 } | |
608 | |
635 if (isGeneric) { | 609 if (isGeneric) { |
636 writeGenericSignature(m.getGenericSignature().asString()); | 610 writeGenericSignature(m.getGenericSignature().asString()); |
637 } | 611 } |
638 } | 612 } |
639 | 613 |
641 ByteCodeRewriter r = new ByteCodeRewriter(m, cpool, code); | 615 ByteCodeRewriter r = new ByteCodeRewriter(m, cpool, code); |
642 r.rewrite(); | 616 r.rewrite(); |
643 } | 617 } |
644 | 618 |
645 protected void writeGenericSignature(String signature) throws IOException { | 619 protected void writeGenericSignature(String signature) throws IOException { |
646 dos.writeShort(_signatureIndex); | 620 writeIndex(_signatureIndex); |
647 if (DEBUG) debugMessage("signature attribute = " + _signatureIndex); | 621 if (DEBUG) debugMessage("signature attribute = " + _signatureIndex); |
648 dos.writeInt(2); | 622 dos.writeInt(2); |
649 Short index = (Short) utf8ToIndex.get(signature); | 623 Short index = (Short) utf8ToIndex.get(signature); |
650 dos.writeShort(index.shortValue()); | 624 dos.writeShort(index.shortValue()); |
651 if (DEBUG) debugMessage("generic signature = " + index); | 625 if (DEBUG) debugMessage("generic signature = " + index); |
652 } | 626 } |
653 | 627 |
654 protected void writeClassAttributes() throws IOException { | 628 protected void writeClassAttributes() throws IOException { |
655 final long flags = klass.getAccessFlags(); | 629 final long flags = klass.getAccessFlags(); |
656 final boolean isSyn = isSynthetic((short) flags); | 630 final boolean hasSyn = hasSyntheticAttribute((short) flags); |
657 | 631 |
658 // check for source file | 632 // check for source file |
659 short classAttributeCount = 0; | 633 short classAttributeCount = 0; |
660 | 634 |
661 if (isSyn) | 635 if (hasSyn) |
662 classAttributeCount++; | 636 classAttributeCount++; |
663 | 637 |
664 Symbol sourceFileName = klass.getSourceFileName(); | 638 Symbol sourceFileName = klass.getSourceFileName(); |
665 if (sourceFileName != null) | 639 if (sourceFileName != null) |
666 classAttributeCount++; | 640 classAttributeCount++; |
675 classAttributeCount++; | 649 classAttributeCount++; |
676 | 650 |
677 dos.writeShort(classAttributeCount); | 651 dos.writeShort(classAttributeCount); |
678 if (DEBUG) debugMessage("class attribute count = " + classAttributeCount); | 652 if (DEBUG) debugMessage("class attribute count = " + classAttributeCount); |
679 | 653 |
680 if (isSyn) | 654 if (hasSyn) |
681 writeSynthetic(); | 655 writeSynthetic(); |
682 | 656 |
683 // write SourceFile, if any | 657 // write SourceFile, if any |
684 if (sourceFileName != null) { | 658 if (sourceFileName != null) { |
685 dos.writeShort(_sourceFileIndex); | 659 writeIndex(_sourceFileIndex); |
686 if (DEBUG) debugMessage("source file attribute = " + _sourceFileIndex); | 660 if (DEBUG) debugMessage("source file attribute = " + _sourceFileIndex); |
687 dos.writeInt(2); | 661 dos.writeInt(2); |
688 Short index = (Short) utf8ToIndex.get(sourceFileName.asString()); | 662 Short index = (Short) utf8ToIndex.get(sourceFileName.asString()); |
689 dos.writeShort(index.shortValue()); | 663 dos.writeShort(index.shortValue()); |
690 if (DEBUG) debugMessage("source file name = " + index); | 664 if (DEBUG) debugMessage("source file name = " + index); |
695 writeGenericSignature(genericSignature.asString()); | 669 writeGenericSignature(genericSignature.asString()); |
696 } | 670 } |
697 | 671 |
698 // write inner classes, if any | 672 // write inner classes, if any |
699 if (numInnerClasses != 0) { | 673 if (numInnerClasses != 0) { |
700 dos.writeShort(_innerClassesIndex); | 674 writeIndex(_innerClassesIndex); |
701 final int innerAttrLen = 2 /* number_of_inner_classes */ + | 675 final int innerAttrLen = 2 /* number_of_inner_classes */ + |
702 numInnerClasses * ( | 676 numInnerClasses * ( |
703 2 /* inner_class_info_index */ + | 677 2 /* inner_class_info_index */ + |
704 2 /* outer_class_info_index */ + | 678 2 /* outer_class_info_index */ + |
705 2 /* inner_class_name_index */ + | 679 2 /* inner_class_name_index */ + |