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 */ +