Skip to content

Commit

Permalink
#4 Refactor Constant Pool item descriptor
Browse files Browse the repository at this point in the history
  • Loading branch information
amosshi committed Sep 7, 2019
1 parent 0f34f48 commit 31f664d
Show file tree
Hide file tree
Showing 21 changed files with 170 additions and 225 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -482,15 +482,21 @@ public byte[] getClassByteArray(final int startIndex, final int length) {
public String getCPDescription(final int index) {
// Invalid index
if (index >= this.constant_pool_count.value) {
return null;
throw new IllegalArgumentException(String.format("Index is bigger than constant pool size. size=%d, index=%d", this.constant_pool_count.value, index));
}

// Special index: empty
if (index == 0) {
return null;
throw new IllegalArgumentException("Constant Pool Index cannot be zero. index=" + index);
}

CPInfo cp = this.constant_pool[index];
if (cp == null) {
// For Double, Long type, each item take two indexs, so there could be some index contains nothing.
throw new IllegalArgumentException("Nothing exist at the Constant Pool Index. index=" + index);
}

return new CPDescr().getCPDescr(index);
return cp.toString(this.constant_pool) + ", " + cp.getName();
}

/**
Expand All @@ -509,185 +515,6 @@ public String toString() {
+ this.methods_count.value.value + " method(s)";
}

///////////////////////////////////////////////////////////////////////////
// Get extracted data
///////////////////////////////////////////////////////////////////////////
// Internal Classes
private static enum Descr_NameAndType {

RAW(1), FIELD(2), METHOD(3);
private final int enum_value;

Descr_NameAndType(final int value) {
this.enum_value = value;
}

public int value() {
return this.enum_value;
}
}

// TODO - Refactor this method into each Constant type
private class CPDescr {

public String getCPDescr(final int index) {
final StringBuilder sb = new StringBuilder(40);

if (index >= 0 && index < ClassFile.this.constant_pool.length) {
CPInfo cp_info = ClassFile.this.constant_pool[index];
if (cp_info != null) {
sb.append(cp_info.getName()).append(": ");
if (cp_info instanceof ConstantUtf8Info) {
sb.append(this.getDescr_Utf8((ConstantUtf8Info) cp_info));
} else if (cp_info instanceof ConstantIntegerInfo) {
sb.append(String.valueOf(((ConstantIntegerInfo) cp_info).integerValue));
} else if (cp_info instanceof ConstantFloatInfo) {
sb.append(String.valueOf(((ConstantFloatInfo) cp_info).floatValue));
} else if (cp_info instanceof ConstantLongInfo) {
sb.append(String.valueOf(((ConstantLongInfo) cp_info).longValue));
} else if (cp_info instanceof ConstantDoubleInfo) {
sb.append(String.valueOf(((ConstantDoubleInfo) cp_info).doubleValue));
} else if (cp_info instanceof ConstantClassInfo) {
sb.append(this.getDescr_Class((ConstantClassInfo) cp_info));
} else if (cp_info instanceof ConstantStringInfo) {
// done here
sb.append(this.getDescr_String((ConstantStringInfo) cp_info));
} else if (cp_info instanceof ConstantFieldrefInfo) {
sb.append(this.getDescr_Fieldref((ConstantFieldrefInfo) cp_info));
} else if (cp_info instanceof ConstantMethodrefInfo) {
sb.append(this.getDescr_Methodref((ConstantMethodrefInfo) cp_info));
} else if (cp_info instanceof ConstantInterfaceMethodrefInfo) {
sb.append(this.getDescr_InterfaceMethodref((ConstantInterfaceMethodrefInfo) cp_info));
} else if (cp_info instanceof ConstantNameAndTypeInfo) {
sb.append(this.getDescr_NameAndType(
(ConstantNameAndTypeInfo) cp_info,
ClassFile.Descr_NameAndType.RAW));
} else if (cp_info instanceof ConstantMethodTypeInfo) {
ConstantMethodTypeInfo mti = (ConstantMethodTypeInfo) cp_info;
sb.append(this.getDescr_Utf8((ConstantUtf8Info) ClassFile.this.constant_pool[mti.descriptor_index.value]));
} else if (cp_info instanceof ConstantDynamicInfo) {
sb.append("bootstrap_method_attr_index = ").append(((ConstantDynamicInfo) cp_info).bootstrap_method_attr_index.value);
sb.append(", name_and_type_index = ").append(this.getCPDescr(((ConstantDynamicInfo) cp_info).name_and_type_index.value));
} else if (cp_info instanceof ConstantInvokeDynamicInfo) {
sb.append("bootstrap_method_attr_index = ").append(((ConstantInvokeDynamicInfo) cp_info).bootstrap_method_attr_index.value);
sb.append(", name_and_type_index = ").append(this.getCPDescr(((ConstantInvokeDynamicInfo) cp_info).name_and_type_index.value));
} else if (cp_info instanceof ConstantMethodHandleInfo) {
sb.append("reference_kind = ").append(ConstantMethodHandleInfo.ReferenceKind.name(((ConstantMethodHandleInfo) cp_info).reference_kind.value));
sb.append(", reference_index = ").append(this.getCPDescr(((ConstantMethodHandleInfo) cp_info).reference_index.value));
} else if (cp_info instanceof ConstantModuleInfo) {
sb.append(this.getDescr_Utf8((ConstantUtf8Info) ClassFile.this.constant_pool[((ConstantModuleInfo) cp_info).name_index.value]));
} else if (cp_info instanceof ConstantPackageInfo) {
sb.append(this.getDescr_Utf8((ConstantUtf8Info) ClassFile.this.constant_pool[((ConstantPackageInfo) cp_info).name_index.value]));
} else {
sb.append("!!! Un-recognized CP type.");
}
} // End if
} else {
sb.append("ERROR - Index (" + index + ") out of bound of constant_pool (" + ClassFile.this.constant_pool.length + ")");
}

return sb.toString();
}

private String getDescr_Utf8(final ConstantUtf8Info info) {
return info.getValue();
}

private String getDescr_Class(final ConstantClassInfo info) {
// The value of the name_index item must be a valid index into the constant_pool table.
// The constant_pool entry at that index must be a CONSTANT_Utf8_info structure
// representing a valid fully qualified class or interface name encoded in internal form.
return SignatureConvertor.ParseClassSignature(this.getDescr_Utf8(
(ConstantUtf8Info) ClassFile.this.constant_pool[info.name_index.value]));
}

private String getDescr_String(final ConstantStringInfo info) {
// The value of the string_index item must be a valid index into the constant_pool table.
// The constant_pool entry at that index must be a CONSTANT_Utf8_info structure
// representing the sequence of characters to which the String object is to be initialized.
return SignatureConvertor.ParseClassSignature(this.getDescr_Utf8(
(ConstantUtf8Info) ClassFile.this.constant_pool[info.string_index.value]));
}

private String getDescr_Fieldref(final ConstantFieldrefInfo info) {
return this.getDescr_ref(
info.class_index.value,
info.name_and_type_index.value,
ClassFile.Descr_NameAndType.FIELD);
}

private String getDescr_Methodref(final ConstantMethodrefInfo info) {
return this.getDescr_ref(
info.class_index.value,
info.name_and_type_index.value,
ClassFile.Descr_NameAndType.METHOD);
}

private String getDescr_InterfaceMethodref(final ConstantInterfaceMethodrefInfo info) {
return this.getDescr_ref(
info.class_index.value,
info.name_and_type_index.value,
ClassFile.Descr_NameAndType.METHOD);
}

private String getDescr_ref(final int classindex, final int natindex, final ClassFile.Descr_NameAndType type) {
final StringBuilder sb = new StringBuilder();
sb.append(this.getDescr_Class((ConstantClassInfo) ClassFile.this.constant_pool[classindex]));
sb.append(".");
sb.append(this.getDescr_NameAndType((ConstantNameAndTypeInfo) ClassFile.this.constant_pool[natindex], type));

return sb.toString();
}

private String getDescr_NameAndType(final ConstantNameAndTypeInfo info, final ClassFile.Descr_NameAndType format) {
final StringBuilder sb = new StringBuilder();
String type;

sb.append(this.getDescr_Utf8((ConstantUtf8Info) ClassFile.this.constant_pool[info.name_index.value]));
sb.append(", ");
type = this.getDescr_Utf8((ConstantUtf8Info) ClassFile.this.constant_pool[info.descriptor_index.value]);

switch (format) {
case RAW:
sb.append(type);
break;

case FIELD:
try {
sb.append("type = ");
sb.append(SignatureConvertor.FieldDescriptorExtractor(type).toString());
} catch (FileFormatException ex) {
Logger.getLogger(ClassFile.class.getName()).log(Level.SEVERE, null, ex);

sb.append(type);
sb.append(" !!! Un-recognized type");
}
break;

case METHOD:
final StringBuilder sb_mtd = new StringBuilder();
try {
sb_mtd.append("parameter = ");
sb_mtd.append(SignatureConvertor.MethodParameters2Readable(type));
sb_mtd.append(", returns = ");
sb_mtd.append(SignatureConvertor.MethodReturnTypeExtractor(type).toString());

sb.append(sb_mtd);
} catch (FileFormatException ex) {
Logger.getLogger(ClassFile.class.getName()).log(Level.SEVERE, null, ex);

sb.append(type);
sb.append(" !!! Un-recognized type");
}
break;
default:
break;
}

return sb.toString();
}
}

/**
* Version numbers of a class file. Together, a major and a minor version
* number determine the version of the class file format. If a class file
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1471,7 +1471,7 @@ protected InstructionParsed parse(final int curPos, final PosDataInputStream pdi
parsed.lookupSwitch.mapoffsets.put(pdis.readInt(), pdis.readInt());
}

parsed.opCodeText = String.format("%s %s", this.name(), parsed.lookupSwitch.toString(curPos));
parsed.opCodeText = String.format("%s %s", this.name(), parsed.lookupSwitch.toString(curPos));
return parsed;
}
},
Expand Down Expand Up @@ -2096,7 +2096,7 @@ public static class LookupSwitch {

public String toString(int currentOffset) {
final StringBuilder sb = new StringBuilder(256);
sb.append("- ").append(this.npairs).append(" Pairs");
sb.append('(').append(this.npairs).append(" Pairs)");
this.mapoffsets.keySet().forEach((key) -> {
Integer value = this.mapoffsets.get(key);
sb.append(String.format("\n case %d. jump to %d (relative offset = %d)", key, value + currentOffset, value));
Expand Down Expand Up @@ -2130,7 +2130,7 @@ public static class TableSwitch {

public String toString(int currentOffset) {
final StringBuilder sb = new StringBuilder(256);
sb.append("- from ").append(this.lowbyte).append(" to ").append(this.highbyte);
sb.append(" (from ").append(this.lowbyte).append(" to ").append(this.highbyte).append(')');
this.jumpoffsets.keySet().forEach((key) -> {
Integer value = this.jumpoffsets.get(key);
sb.append(String.format("\n case %d. jump to %d (relative offset = %d) ", key, value + currentOffset, value));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@
*/
public abstract class CPInfo extends FileComponent {

/**
* Warning message for un-recognized type.
*/
protected static final String UNRECOGNIZED_TYPE = " !!! Un-recognized type";

/**
* Each item in the {@link ClassFile#constant_pool} table must begin with a
* 1-byte {@link #tag} indicating the kind of <code>cp_info</code> entry.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ public String toString(CPInfo[] constant_pool) {
// The value of the name_index item must be a valid index into the constant_pool table.
// The constant_pool entry at that index must be a CONSTANT_Utf8_info structure
// representing a valid fully qualified class or interface name encoded in internal form.
final String classtype = SignatureConvertor.ParseClassSignature(((ConstantUtf8Info) constant_pool[this.name_index.value]).getValue());
return this.getName() + ". " + classtype;
return SignatureConvertor.ParseClassSignature(((ConstantUtf8Info) constant_pool[this.name_index.value]).getValue());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,6 @@ public String getDescription() {

@Override
public String toString(CPInfo[] constant_pool) {
return this.getName() + ". " + this.doubleValue;
return String.valueOf(this.doubleValue);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ public String getDescription() {

@Override
public String toString(CPInfo[] constant_pool) {
return null;
// TODO Improve this logic with test case
final StringBuilder sb = new StringBuilder(64);
sb.append("bootstrap_method_attr_index = ").append(this.bootstrap_method_attr_index.value);
sb.append(", name_and_type_index = ").append(constant_pool[this.name_and_type_index.value].toString(constant_pool));
return sb.toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,13 @@
package org.freeinternals.format.classfile.constant;

import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.freeinternals.commonlib.core.PosDataInputStream;
import org.freeinternals.format.FileFormatException;
import org.freeinternals.format.classfile.ClassFile;
import org.freeinternals.format.classfile.JavaSEVersion;
import org.freeinternals.format.classfile.SignatureConvertor;

/**
* The class for the {@code CONSTANT_Fieldref_info} structure in constant pool.
Expand All @@ -32,6 +36,32 @@
public class ConstantFieldrefInfo extends ConstantRefInfo {

ConstantFieldrefInfo(final PosDataInputStream posDataInputStream) throws IOException {
super(CPInfo.ConstantType.CONSTANT_Fieldref.tag, posDataInputStream, ConstantType.CONSTANT_Fieldref.name(), ClassFile.Version.Format_45_3, JavaSEVersion.Version_1_0_2);
super(CPInfo.ConstantType.CONSTANT_Fieldref.tag, posDataInputStream, ClassFile.Version.Format_45_3, JavaSEVersion.Version_1_0_2);
}

@Override
public String getName() {
return ConstantType.CONSTANT_Fieldref.name();
}

@Override
public String toString(CPInfo[] constant_pool) {
// Class
String clazz = constant_pool[this.class_index.value].toString(constant_pool);

// Name and Type
ConstantNameAndTypeInfo nameType = (ConstantNameAndTypeInfo) constant_pool[this.name_and_type_index.value];
String name = constant_pool[nameType.name_index.value].toString(constant_pool);
String type = constant_pool[nameType.descriptor_index.value].toString(constant_pool);
String typeDesc;

try {
typeDesc = SignatureConvertor.FieldDescriptorExtractor(type).toString();
} catch (FileFormatException ex) {
typeDesc = type + UNRECOGNIZED_TYPE;
Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, "Failed to parse the field type: " + type, ex);
}

return String.format("%s.%s : %s", clazz, name, typeDesc);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,6 @@ public String getDescription() {

@Override
public String toString(CPInfo[] constant_pool) {
return this.getName() + ". " + this.floatValue;
return String.valueOf(this.floatValue);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,6 @@ public String getDescription() {

@Override
public String toString(CPInfo[] constant_pool) {
return String.format("%s. %d", this.getName(), this.integerValue);
return String.valueOf(this.integerValue);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,16 @@
public class ConstantInterfaceMethodrefInfo extends ConstantRefInfo {

ConstantInterfaceMethodrefInfo(final PosDataInputStream posDataInputStream) throws IOException {
super(CPInfo.ConstantType.CONSTANT_InterfaceMethodref.tag, posDataInputStream, ConstantType.CONSTANT_InterfaceMethodref.name(), ClassFile.Version.Format_45_3, JavaSEVersion.Version_1_0_2);
super(CPInfo.ConstantType.CONSTANT_InterfaceMethodref.tag, posDataInputStream, ClassFile.Version.Format_45_3, JavaSEVersion.Version_1_0_2);
}

@Override
public String getName() {
return ConstantType.CONSTANT_InterfaceMethodref.name();
}

@Override
public String toString(CPInfo[] constant_pool) {
return super.toString4Method(constant_pool);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,10 @@ public String getDescription() {

@Override
public String toString(CPInfo[] constant_pool) {
return null;
// TODO Improve this logic with test case
final StringBuilder sb = new StringBuilder(64);
sb.append("bootstrap_method_attr_index = ").append(this.bootstrap_method_attr_index.value);
sb.append(", name_and_type_index = ").append(constant_pool[this.name_and_type_index.value].toString(constant_pool));
return sb.toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,6 @@ public String getDescription() {

@Override
public String toString(CPInfo[] constant_pool) {
return this.getName() + ". " + this.longValue;
return String.valueOf(this.longValue);
}
}
Loading

0 comments on commit 31f664d

Please sign in to comment.