6826261: class file dumping from SA is broken
Reviewed-by: kvn, jcoomes
This commit is contained in:
parent
090346b4e8
commit
5f10e8e82e
@ -142,34 +142,35 @@ public interface ClassConstants
|
|||||||
// from jvm.h
|
// from jvm.h
|
||||||
|
|
||||||
public static final long JVM_RECOGNIZED_CLASS_MODIFIERS = (JVM_ACC_PUBLIC |
|
public static final long JVM_RECOGNIZED_CLASS_MODIFIERS = (JVM_ACC_PUBLIC |
|
||||||
JVM_ACC_FINAL |
|
JVM_ACC_FINAL |
|
||||||
JVM_ACC_SUPER |
|
JVM_ACC_SUPER |
|
||||||
JVM_ACC_INTERFACE |
|
JVM_ACC_INTERFACE |
|
||||||
JVM_ACC_ABSTRACT |
|
JVM_ACC_ABSTRACT |
|
||||||
JVM_ACC_ANNOTATION |
|
JVM_ACC_ANNOTATION |
|
||||||
JVM_ACC_SYNTHETIC);
|
JVM_ACC_ENUM |
|
||||||
|
JVM_ACC_SYNTHETIC);
|
||||||
|
|
||||||
|
|
||||||
public static final long JVM_RECOGNIZED_FIELD_MODIFIERS = (JVM_ACC_PUBLIC |
|
public static final long JVM_RECOGNIZED_FIELD_MODIFIERS = (JVM_ACC_PUBLIC |
|
||||||
JVM_ACC_PRIVATE |
|
JVM_ACC_PRIVATE |
|
||||||
JVM_ACC_PROTECTED |
|
JVM_ACC_PROTECTED |
|
||||||
JVM_ACC_STATIC |
|
JVM_ACC_STATIC |
|
||||||
JVM_ACC_FINAL |
|
JVM_ACC_FINAL |
|
||||||
JVM_ACC_VOLATILE |
|
JVM_ACC_VOLATILE |
|
||||||
JVM_ACC_TRANSIENT |
|
JVM_ACC_TRANSIENT |
|
||||||
JVM_ACC_ENUM |
|
JVM_ACC_ENUM |
|
||||||
JVM_ACC_SYNTHETIC);
|
JVM_ACC_SYNTHETIC);
|
||||||
|
|
||||||
public static final long JVM_RECOGNIZED_METHOD_MODIFIERS = (JVM_ACC_PUBLIC |
|
public static final long JVM_RECOGNIZED_METHOD_MODIFIERS = (JVM_ACC_PUBLIC |
|
||||||
JVM_ACC_PRIVATE |
|
JVM_ACC_PRIVATE |
|
||||||
JVM_ACC_PROTECTED |
|
JVM_ACC_PROTECTED |
|
||||||
JVM_ACC_STATIC |
|
JVM_ACC_STATIC |
|
||||||
JVM_ACC_FINAL |
|
JVM_ACC_FINAL |
|
||||||
JVM_ACC_SYNCHRONIZED |
|
JVM_ACC_SYNCHRONIZED |
|
||||||
JVM_ACC_BRIDGE |
|
JVM_ACC_BRIDGE |
|
||||||
JVM_ACC_VARARGS |
|
JVM_ACC_VARARGS |
|
||||||
JVM_ACC_NATIVE |
|
JVM_ACC_NATIVE |
|
||||||
JVM_ACC_ABSTRACT |
|
JVM_ACC_ABSTRACT |
|
||||||
JVM_ACC_STRICT |
|
JVM_ACC_STRICT |
|
||||||
JVM_ACC_SYNTHETIC);
|
JVM_ACC_SYNTHETIC);
|
||||||
}
|
}
|
||||||
|
@ -89,29 +89,6 @@ public class ByteCodeRewriter
|
|||||||
// update the code buffer hotspot specific bytecode with the jvm bytecode
|
// update the code buffer hotspot specific bytecode with the jvm bytecode
|
||||||
code[bci] = (byte) (0xFF & bytecode);
|
code[bci] = (byte) (0xFF & bytecode);
|
||||||
|
|
||||||
// RewriteFrequentPairs
|
|
||||||
if(hotspotcode == Bytecodes._fast_iaccess_0 ||
|
|
||||||
hotspotcode == Bytecodes._fast_aaccess_0 ||
|
|
||||||
hotspotcode == Bytecodes._fast_faccess_0) {
|
|
||||||
// rewrite next bytecode as _getfield
|
|
||||||
bci++;
|
|
||||||
code[bci] = (byte) (0xFF & Bytecodes._getfield);
|
|
||||||
bytecode = Bytecodes._getfield;
|
|
||||||
hotspotcode = Bytecodes._getfield;
|
|
||||||
} else if (hotspotcode == Bytecodes._fast_iload2) {
|
|
||||||
// rewrite next bytecode as _iload
|
|
||||||
bci++;
|
|
||||||
code[bci] = (byte) (0xFF & Bytecodes._iload);
|
|
||||||
bytecode = Bytecodes._iload;
|
|
||||||
hotspotcode = Bytecodes._iload;
|
|
||||||
} else if (hotspotcode == Bytecodes._fast_icaload) {
|
|
||||||
// rewrite next bytecode as _caload
|
|
||||||
bci++;
|
|
||||||
code[bci] = (byte) (0xFF & Bytecodes._caload);
|
|
||||||
bytecode = Bytecodes._caload;
|
|
||||||
bytecode = Bytecodes._caload;
|
|
||||||
}
|
|
||||||
|
|
||||||
short cpoolIndex = 0;
|
short cpoolIndex = 0;
|
||||||
switch (bytecode) {
|
switch (bytecode) {
|
||||||
// bytecodes with ConstantPoolCache index
|
// bytecodes with ConstantPoolCache index
|
||||||
|
@ -59,8 +59,14 @@ public class ClassDump extends Tool {
|
|||||||
SystemDictionary dict = VM.getVM().getSystemDictionary();
|
SystemDictionary dict = VM.getVM().getSystemDictionary();
|
||||||
dict.classesDo(new SystemDictionary.ClassVisitor() {
|
dict.classesDo(new SystemDictionary.ClassVisitor() {
|
||||||
public void visit(Klass k) {
|
public void visit(Klass k) {
|
||||||
if (k instanceof InstanceKlass)
|
if (k instanceof InstanceKlass) {
|
||||||
dumpKlass((InstanceKlass) k);
|
try {
|
||||||
|
dumpKlass((InstanceKlass) k);
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println(k.getName().asString());
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,6 @@ public class ClassWriter implements /* imports */ ClassConstants
|
|||||||
protected InstanceKlass klass;
|
protected InstanceKlass klass;
|
||||||
protected DataOutputStream dos;
|
protected DataOutputStream dos;
|
||||||
protected ConstantPool cpool;
|
protected ConstantPool cpool;
|
||||||
protected boolean is15Format;
|
|
||||||
|
|
||||||
// Map between class name to index of type CONSTANT_Class
|
// Map between class name to index of type CONSTANT_Class
|
||||||
protected Map classToIndex = new HashMap();
|
protected Map classToIndex = new HashMap();
|
||||||
@ -73,7 +72,6 @@ public class ClassWriter implements /* imports */ ClassConstants
|
|||||||
klass = kls;
|
klass = kls;
|
||||||
dos = new DataOutputStream(os);
|
dos = new DataOutputStream(os);
|
||||||
cpool = klass.getConstants();
|
cpool = klass.getConstants();
|
||||||
is15Format = is15ClassFile();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void write() throws IOException {
|
public void write() throws IOException {
|
||||||
@ -82,7 +80,7 @@ public class ClassWriter implements /* imports */ ClassConstants
|
|||||||
// write magic
|
// write magic
|
||||||
dos.writeInt(0xCAFEBABE);
|
dos.writeInt(0xCAFEBABE);
|
||||||
|
|
||||||
writeVersion(is15Format);
|
writeVersion();
|
||||||
writeConstantPool();
|
writeConstantPool();
|
||||||
writeClassAccessFlags();
|
writeClassAccessFlags();
|
||||||
writeThisClass();
|
writeThisClass();
|
||||||
@ -96,43 +94,14 @@ public class ClassWriter implements /* imports */ ClassConstants
|
|||||||
dos.flush();
|
dos.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean is15ClassFile() {
|
protected void writeVersion() throws IOException {
|
||||||
// if klass has generic signature, then it is 1.5 class file.
|
dos.writeShort((short)klass.minorVersion());
|
||||||
if (klass.getGenericSignature() != null) {
|
dos.writeShort((short)klass.majorVersion());
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if atleast one method has generic signature
|
|
||||||
// , then we have 1.5 class file.
|
|
||||||
ObjArray methods = klass.getMethods();
|
|
||||||
final int numMethods = (int) methods.getLength();
|
|
||||||
for (int m = 0; m < numMethods; m++) {
|
|
||||||
Method curMethod = (Method) methods.getObjAt(m);
|
|
||||||
if (curMethod.getGenericSignature() != null) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if atleast one field has non-zero generic signature index, then we have
|
|
||||||
// 1.5 class file
|
|
||||||
TypeArray fields = klass.getFields();
|
|
||||||
final int numFields = (int) fields.getLength();
|
|
||||||
for (int f = 0; f < numFields; f += InstanceKlass.NEXT_OFFSET) {
|
|
||||||
short genSigIndex = fields.getShortAt(f + InstanceKlass.GENERIC_SIGNATURE_INDEX_OFFSET);
|
|
||||||
if (genSigIndex != (short)0) return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void writeVersion(boolean is15Format) throws IOException {
|
protected void writeIndex(int index) throws IOException {
|
||||||
if (is15Format) {
|
if (index == 0) throw new InternalError();
|
||||||
dos.writeShort(MINOR_VERSION);
|
dos.writeShort(index);
|
||||||
dos.writeShort(MAJOR_VERSION);
|
|
||||||
} else {
|
|
||||||
dos.writeShort(MINOR_VERSION_OLD);
|
|
||||||
dos.writeShort(MAJOR_VERSION_OLD);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void writeConstantPool() throws IOException {
|
protected void writeConstantPool() throws IOException {
|
||||||
@ -392,8 +361,8 @@ public class ClassWriter implements /* imports */ ClassConstants
|
|||||||
if (DEBUG) debugMessage("\tfield name = " + nameIndex + ", signature = " + signatureIndex);
|
if (DEBUG) debugMessage("\tfield name = " + nameIndex + ", signature = " + signatureIndex);
|
||||||
|
|
||||||
short fieldAttributeCount = 0;
|
short fieldAttributeCount = 0;
|
||||||
boolean isSyn = isSynthetic(accessFlags);
|
boolean hasSyn = hasSyntheticAttribute(accessFlags);
|
||||||
if (isSyn)
|
if (hasSyn)
|
||||||
fieldAttributeCount++;
|
fieldAttributeCount++;
|
||||||
|
|
||||||
short initvalIndex = fields.getShortAt(index + InstanceKlass.INITVAL_INDEX_OFFSET);
|
short initvalIndex = fields.getShortAt(index + InstanceKlass.INITVAL_INDEX_OFFSET);
|
||||||
@ -407,18 +376,18 @@ public class ClassWriter implements /* imports */ ClassConstants
|
|||||||
dos.writeShort(fieldAttributeCount);
|
dos.writeShort(fieldAttributeCount);
|
||||||
|
|
||||||
// write synthetic, if applicable
|
// write synthetic, if applicable
|
||||||
if (isSyn)
|
if (hasSyn)
|
||||||
writeSynthetic();
|
writeSynthetic();
|
||||||
|
|
||||||
if (initvalIndex != 0) {
|
if (initvalIndex != 0) {
|
||||||
dos.writeShort(_constantValueIndex);
|
writeIndex(_constantValueIndex);
|
||||||
dos.writeInt(2);
|
dos.writeInt(2);
|
||||||
dos.writeShort(initvalIndex);
|
dos.writeShort(initvalIndex);
|
||||||
if (DEBUG) debugMessage("\tfield init value = " + initvalIndex);
|
if (DEBUG) debugMessage("\tfield init value = " + initvalIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (genSigIndex != 0) {
|
if (genSigIndex != 0) {
|
||||||
dos.writeShort(_signatureIndex);
|
writeIndex(_signatureIndex);
|
||||||
dos.writeInt(2);
|
dos.writeInt(2);
|
||||||
dos.writeShort(genSigIndex);
|
dos.writeShort(genSigIndex);
|
||||||
if (DEBUG) debugMessage("\tfield generic signature index " + genSigIndex);
|
if (DEBUG) debugMessage("\tfield generic signature index " + genSigIndex);
|
||||||
@ -430,8 +399,13 @@ public class ClassWriter implements /* imports */ ClassConstants
|
|||||||
return (accessFlags & (short) JVM_ACC_SYNTHETIC) != 0;
|
return (accessFlags & (short) JVM_ACC_SYNTHETIC) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected boolean hasSyntheticAttribute(short accessFlags) {
|
||||||
|
// Check if flags have the attribute and if the constant pool contains an entry for it.
|
||||||
|
return isSynthetic(accessFlags) && _syntheticIndex != 0;
|
||||||
|
}
|
||||||
|
|
||||||
protected void writeSynthetic() throws IOException {
|
protected void writeSynthetic() throws IOException {
|
||||||
dos.writeShort(_syntheticIndex);
|
writeIndex(_syntheticIndex);
|
||||||
dos.writeInt(0);
|
dos.writeInt(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -459,8 +433,8 @@ public class ClassWriter implements /* imports */ ClassConstants
|
|||||||
|
|
||||||
short methodAttributeCount = 0;
|
short methodAttributeCount = 0;
|
||||||
|
|
||||||
final boolean isSyn = isSynthetic((short)accessFlags);
|
final boolean hasSyn = hasSyntheticAttribute((short)accessFlags);
|
||||||
if (isSyn)
|
if (hasSyn)
|
||||||
methodAttributeCount++;
|
methodAttributeCount++;
|
||||||
|
|
||||||
final boolean hasCheckedExceptions = m.hasCheckedExceptions();
|
final boolean hasCheckedExceptions = m.hasCheckedExceptions();
|
||||||
@ -478,27 +452,11 @@ public class ClassWriter implements /* imports */ ClassConstants
|
|||||||
dos.writeShort(methodAttributeCount);
|
dos.writeShort(methodAttributeCount);
|
||||||
if (DEBUG) debugMessage("\tmethod attribute count = " + methodAttributeCount);
|
if (DEBUG) debugMessage("\tmethod attribute count = " + methodAttributeCount);
|
||||||
|
|
||||||
if (isSyn) {
|
if (hasSyn) {
|
||||||
if (DEBUG) debugMessage("\tmethod is synthetic");
|
if (DEBUG) debugMessage("\tmethod is synthetic");
|
||||||
writeSynthetic();
|
writeSynthetic();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasCheckedExceptions) {
|
|
||||||
CheckedExceptionElement[] exceptions = m.getCheckedExceptions();
|
|
||||||
dos.writeShort(_exceptionsIndex);
|
|
||||||
|
|
||||||
int attrSize = 2 /* number_of_exceptions */ +
|
|
||||||
exceptions.length * 2 /* exception_index */;
|
|
||||||
dos.writeInt(attrSize);
|
|
||||||
dos.writeShort(exceptions.length);
|
|
||||||
if (DEBUG) debugMessage("\tmethod has " + exceptions.length
|
|
||||||
+ " checked exception(s)");
|
|
||||||
for (int e = 0; e < exceptions.length; e++) {
|
|
||||||
short cpIndex = (short) exceptions[e].getClassCPIndex();
|
|
||||||
dos.writeShort(cpIndex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isCodeAvailable) {
|
if (isCodeAvailable) {
|
||||||
byte[] code = m.getByteCode();
|
byte[] code = m.getByteCode();
|
||||||
short codeAttrCount = 0;
|
short codeAttrCount = 0;
|
||||||
@ -574,7 +532,7 @@ public class ClassWriter implements /* imports */ ClassConstants
|
|||||||
|
|
||||||
// start writing Code
|
// start writing Code
|
||||||
|
|
||||||
dos.writeShort(_codeIndex);
|
writeIndex(_codeIndex);
|
||||||
|
|
||||||
dos.writeInt(codeSize);
|
dos.writeInt(codeSize);
|
||||||
if (DEBUG) debugMessage("\tcode attribute length = " + codeSize);
|
if (DEBUG) debugMessage("\tcode attribute length = " + codeSize);
|
||||||
@ -608,7 +566,7 @@ public class ClassWriter implements /* imports */ ClassConstants
|
|||||||
|
|
||||||
// write LineNumberTable, if available.
|
// write LineNumberTable, if available.
|
||||||
if (hasLineNumberTable) {
|
if (hasLineNumberTable) {
|
||||||
dos.writeShort(_lineNumberTableIndex);
|
writeIndex(_lineNumberTableIndex);
|
||||||
dos.writeInt(lineNumberAttrLen);
|
dos.writeInt(lineNumberAttrLen);
|
||||||
dos.writeShort((short) lineNumberTable.length);
|
dos.writeShort((short) lineNumberTable.length);
|
||||||
for (int l = 0; l < lineNumberTable.length; l++) {
|
for (int l = 0; l < lineNumberTable.length; l++) {
|
||||||
@ -619,7 +577,7 @@ public class ClassWriter implements /* imports */ ClassConstants
|
|||||||
|
|
||||||
// write LocalVariableTable, if available.
|
// write LocalVariableTable, if available.
|
||||||
if (hasLocalVariableTable) {
|
if (hasLocalVariableTable) {
|
||||||
dos.writeShort((short) _localVariableTableIndex);
|
writeIndex((short) _localVariableTableIndex);
|
||||||
dos.writeInt(localVarAttrLen);
|
dos.writeInt(localVarAttrLen);
|
||||||
dos.writeShort((short) localVariableTable.length);
|
dos.writeShort((short) localVariableTable.length);
|
||||||
for (int l = 0; l < localVariableTable.length; l++) {
|
for (int l = 0; l < localVariableTable.length; l++) {
|
||||||
@ -632,6 +590,22 @@ public class ClassWriter implements /* imports */ ClassConstants
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hasCheckedExceptions) {
|
||||||
|
CheckedExceptionElement[] exceptions = m.getCheckedExceptions();
|
||||||
|
writeIndex(_exceptionsIndex);
|
||||||
|
|
||||||
|
int attrSize = 2 /* number_of_exceptions */ +
|
||||||
|
exceptions.length * 2 /* exception_index */;
|
||||||
|
dos.writeInt(attrSize);
|
||||||
|
dos.writeShort(exceptions.length);
|
||||||
|
if (DEBUG) debugMessage("\tmethod has " + exceptions.length
|
||||||
|
+ " checked exception(s)");
|
||||||
|
for (int e = 0; e < exceptions.length; e++) {
|
||||||
|
short cpIndex = (short) exceptions[e].getClassCPIndex();
|
||||||
|
dos.writeShort(cpIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (isGeneric) {
|
if (isGeneric) {
|
||||||
writeGenericSignature(m.getGenericSignature().asString());
|
writeGenericSignature(m.getGenericSignature().asString());
|
||||||
}
|
}
|
||||||
@ -643,7 +617,7 @@ public class ClassWriter implements /* imports */ ClassConstants
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void writeGenericSignature(String signature) throws IOException {
|
protected void writeGenericSignature(String signature) throws IOException {
|
||||||
dos.writeShort(_signatureIndex);
|
writeIndex(_signatureIndex);
|
||||||
if (DEBUG) debugMessage("signature attribute = " + _signatureIndex);
|
if (DEBUG) debugMessage("signature attribute = " + _signatureIndex);
|
||||||
dos.writeInt(2);
|
dos.writeInt(2);
|
||||||
Short index = (Short) utf8ToIndex.get(signature);
|
Short index = (Short) utf8ToIndex.get(signature);
|
||||||
@ -653,12 +627,12 @@ public class ClassWriter implements /* imports */ ClassConstants
|
|||||||
|
|
||||||
protected void writeClassAttributes() throws IOException {
|
protected void writeClassAttributes() throws IOException {
|
||||||
final long flags = klass.getAccessFlags();
|
final long flags = klass.getAccessFlags();
|
||||||
final boolean isSyn = isSynthetic((short) flags);
|
final boolean hasSyn = hasSyntheticAttribute((short) flags);
|
||||||
|
|
||||||
// check for source file
|
// check for source file
|
||||||
short classAttributeCount = 0;
|
short classAttributeCount = 0;
|
||||||
|
|
||||||
if (isSyn)
|
if (hasSyn)
|
||||||
classAttributeCount++;
|
classAttributeCount++;
|
||||||
|
|
||||||
Symbol sourceFileName = klass.getSourceFileName();
|
Symbol sourceFileName = klass.getSourceFileName();
|
||||||
@ -677,12 +651,12 @@ public class ClassWriter implements /* imports */ ClassConstants
|
|||||||
dos.writeShort(classAttributeCount);
|
dos.writeShort(classAttributeCount);
|
||||||
if (DEBUG) debugMessage("class attribute count = " + classAttributeCount);
|
if (DEBUG) debugMessage("class attribute count = " + classAttributeCount);
|
||||||
|
|
||||||
if (isSyn)
|
if (hasSyn)
|
||||||
writeSynthetic();
|
writeSynthetic();
|
||||||
|
|
||||||
// write SourceFile, if any
|
// write SourceFile, if any
|
||||||
if (sourceFileName != null) {
|
if (sourceFileName != null) {
|
||||||
dos.writeShort(_sourceFileIndex);
|
writeIndex(_sourceFileIndex);
|
||||||
if (DEBUG) debugMessage("source file attribute = " + _sourceFileIndex);
|
if (DEBUG) debugMessage("source file attribute = " + _sourceFileIndex);
|
||||||
dos.writeInt(2);
|
dos.writeInt(2);
|
||||||
Short index = (Short) utf8ToIndex.get(sourceFileName.asString());
|
Short index = (Short) utf8ToIndex.get(sourceFileName.asString());
|
||||||
@ -697,7 +671,7 @@ public class ClassWriter implements /* imports */ ClassConstants
|
|||||||
|
|
||||||
// write inner classes, if any
|
// write inner classes, if any
|
||||||
if (numInnerClasses != 0) {
|
if (numInnerClasses != 0) {
|
||||||
dos.writeShort(_innerClassesIndex);
|
writeIndex(_innerClassesIndex);
|
||||||
final int innerAttrLen = 2 /* number_of_inner_classes */ +
|
final int innerAttrLen = 2 /* number_of_inner_classes */ +
|
||||||
numInnerClasses * (
|
numInnerClasses * (
|
||||||
2 /* inner_class_info_index */ +
|
2 /* inner_class_info_index */ +
|
||||||
|
Loading…
x
Reference in New Issue
Block a user