Программа просмотра Java-классов (Java Class Viewer) - Получение информации о файле класса
ОГЛАВЛЕНИЕ
2. Получение информации о файле класса
Как только мы успешно получим экземпляр ClassFile, мы можем получить информацию о файле класса посредством методов getXxxxx.
Вот пример вывода информации всех компонент файла класса:
// ArticleCodeDemo.src.zip - org.freeinternals.demo.jCFL_CodeDemo.printClassFile()
// Версии Minor и Major
MinorVersion minorVersion = classfile.getMinorVersion();
System.out.println("Class File Minor Version: " + minorVersion.getValue());
MajorVersion majorVersion = classfile.getMajorVersion();
System.out.println("Class File Major Version: " + majorVersion.getValue());
// Набор констант
CPCount cpCount = classfile.getCPCount();
System.out.println("Constant Pool size: " + cpCount.getValue());
AbstractCPInfo[] cpArray = classfile.getConstantPool();
for (int i = 1; i < cpCount.getValue(); i++) {
System.out.println(
String.format("Constant Pool [%d]: %s", i, classfile.getCPDescription(i)));
short tag = cpArray[i].getTag();
if ((tag == AbstractCPInfo.CONSTANT_Double) ||
(tag == AbstractCPInfo.CONSTANT_Long)) {
i++;
}
}
// Флаг доступа, this и супер-класс
AccessFlags accessFlags = classfile.getAccessFlags();
System.out.println("Class Modifier: " + accessFlags.getModifiers());
ThisClass thisClass = classfile.getThisClass();
System.out.println("This Class Name Index: " + thisClass.getValue());
System.out.println("This Class Name: " +
classfile.getCPDescription(thisClass.getValue()));
SuperClass superClass = classfile.getSuperClass();
System.out.println("Super Class Name Index: " + superClass.getValue());
if (superClass.getValue() == 0) {
System.out.println("Super Class Name: java.lang.Object");
} else {
System.out.println("Super Class Name: " +
classfile.getCPDescription(superClass.getValue()));
}
// Интерфейсы
InterfaceCount interfactCount = classfile.getInterfacesCount();
System.out.println("Interface Count: " + interfactCount.getValue());
if (interfactCount.getValue() > 0) {
Interface[] interfaceArray = classfile.getInterfaces();
for (int i = 0; i < interfaceArray.length; i++) {
System.out.println(
String.format("Interface [%d] Name Index: %d", i,
interfaceArray[i].getValue()));
System.out.println(
String.format("Interface [%d] Name: %s", i,
classfile.getCPDescription(interfaceArray[i].getValue())));
}
}
// Поля
FieldCount fieldCount = classfile.getFieldCount();
System.out.println("Field count: " + fieldCount.getValue());
if (fieldCount.getValue() > 0) {
FieldInfo[] fieldArray = classfile.getFields();
for (int i = 0; i < fieldArray.length; i++) {
System.out.println(String.format("Field [%d]: %s", i,
fieldArray[i].getDeclaration()));
}
}
// Методы
MethodCount methodCount = classfile.getMethodCount();
System.out.println("Method count: " + methodCount.getValue());
if (methodCount.getValue() > 0) {
MethodInfo[] methodArray = classfile.getMethods();
for (int i = 0; i < methodArray.length; i++) {
System.out.println(String.format("Method [%d]: %s", i,
methodArray[i].getDeclaration()));
}
}
// Атрибуты
AttributeCount attributeCount = classfile.getAttributeCount();
System.out.println("Attribute count: " + attributeCount.getValue());
AttributeInfo[] attributeArray = classfile.getAttributes();
for (int i = 0; i < attributeArray.length; i++) {
System.out.println(String.format("Attribute [%d]: %s", i,
attributeArray[i].getName()));
}
Вот некоторые заметки по поводу указанного выше кода.
Набор констант: это набор констант (Сonstant pool) начиная с индекса 1 до (constant_pool_count-1); также CONSTANT_Long_info и CONSTANT_Double_info получат две позиции индексов, в то время как другие типы всего лишь получат одну позицию.
Суперкласс: индекс суперкласса будет равен нулю только тогда, когда текущим классом будет java.lang.Object. В противном случае, он должен быть элементом в наборе констант.
Интерфейсы и поля: класс может не иметь ни интерфейсов, ни полей, потому нам необходимо проверить переменные InterfaceCount и FieldCount до того, как мы получим массив интерфейса/поля.
Методы: если класс не является внутренним, то он должен иметь хотя бы один метод, который будет являться конструктором экземпляров по умолчанию, созданным javac; но для внутреннего класса методы нет возможности создать. Потому нам необходимо проверить равенство переменной MethodCount нулю.
Атрибуты: один класс должен иметь хотя бы один атрибут - SourceFile; нам не нужно добавлять логику для него.
Используя код, похожий на тот, что указан выше, вам не составит труда написать визуальный элемент управления интерфейсом для файла класса. А также будет легко написать любое приложение по анализу мета-данных в классе.