📄 classfile.java
字号:
/*
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public
License as published by the Free Software Foundation; either
version 2 of the license, or (at your option) any later version.
*/
package org.gjt.jclasslib.structures;
import org.gjt.jclasslib.io.Log;
import org.gjt.jclasslib.structures.constants.ConstantLargeNumeric;
import org.gjt.jclasslib.structures.constants.ConstantUtf8Info;
import java.io.*;
import java.util.HashMap;
/**
* The class file structure in which all other structures are hooked up.
*
* @author <a href="mailto:jclasslib@ej-technologies.com">Ingo Kegel</a>, <a href="mailto:vitor.carreira@gmail.com">Vitor Carreira</a>
* @version $Revision: 1.3 $ $Date: 2006/09/04 15:43:18 $
*/
public class ClassFile extends AbstractStructureWithAttributes {
/**
* Set this JVM System property to true to skip reading of constant pool
* entries. This is not advisable, since most sunsequent operations on the
* class file structure will fail.
*/
public static final String SYSTEM_PROPERTY_SKIP_CONSTANT_POOL = "jclasslib.io.skipConstantPool";
private static final int MAGIC_NUMBER = 0xcafebabe;
private final boolean skipConstantPool;
private int minorVersion;
private int majorVersion;
private CPInfo[] constantPool;
private HashMap<CPInfo, Integer> constantPoolEntryToIndex = new HashMap<CPInfo, Integer>();
private int accessFlags;
private int thisClass;
private int superClass;
private int[] interfaces;
private FieldInfo[] fields;
private MethodInfo[] methods;
/**
* Constructor.
*/
public ClassFile() {
skipConstantPool = Boolean.getBoolean(SYSTEM_PROPERTY_SKIP_CONSTANT_POOL);
setClassFile(this);
}
/**
* Get the minor version of the class file format.
*
* @return the minor version
*/
public int getMinorVersion() {
return minorVersion;
}
/**
* Set the minor version of the class file format.
*
* @param minorVersion the minor version
*/
public void setMinorVersion(int minorVersion) {
this.minorVersion = minorVersion;
}
/**
* Get the major version of the class file format.
*
* @return the major version
*/
public int getMajorVersion() {
return majorVersion;
}
/**
* Set the major version of the class file format.
*
* @param majorVersion the major version
*/
public void setMajorVersion(int majorVersion) {
this.majorVersion = majorVersion;
}
/**
* Get the array with all constant pool entries.
*
* @return the array
*/
public CPInfo[] getConstantPool() {
return constantPool;
}
/**
* Get the index of an equivalent constant pool entry.
*
* @param cpInfo the constant pool entry
* @return the index, -1 if no equivalent constant pool entry can be found
*/
public int getConstantPoolIndex(CPInfo cpInfo) {
Integer index = (Integer)constantPoolEntryToIndex.get(cpInfo);
if (index != null) {
return index.intValue();
} else {
return -1;
}
}
/**
* Set the array with all constant pool entries. An internal hash map
* will need to be recalulated. If you add to the end of the constant
* pool, use <tt>enlargeConstantPool</tt>.
*
* @param constantPool the array
*/
public void setConstantPool(CPInfo[] constantPool) {
this.constantPool = constantPool;
for (int i = 0; i < constantPool.length; i++) {
constantPoolEntryToIndex.put(constantPool[i], new Integer(i));
}
}
/**
* Set the array with all constant pool entries where the new array
* of constant pool entries starts with the old constant pool. If
* you delete entries, use <tt>setConstantPool</tt>.
*
* @param enlargedConstantPool the array
*/
public void enlargeConstantPool(CPInfo[] enlargedConstantPool) {
int startIndex = constantPool == null ? 0 : constantPool.length;
this.constantPool = enlargedConstantPool;
for (int i = startIndex; i < constantPool.length; i++) {
if (constantPool[i] != null) {
constantPoolEntryToIndex.put(constantPool[i], new Integer(i));
}
}
}
/**
* Register the constant pool entry at a given index, so that it can
* be found through the <tt>getConstantPoolIndex</tt> method.
*
* @param index the index
*/
public void registerConstantPoolEntry(int index) {
constantPoolEntryToIndex.put(constantPool[index], new Integer(index));
}
/**
* Unregister the constant pool entry at a given index, so that it can
* no longer be found through the <tt>getConstantPoolIndex</tt> method.
*
* @param index the index
*/
public void unregisterConstantPoolEntry(int index) {
constantPoolEntryToIndex.remove(constantPool[index]);
}
/**
* Get the access flags of this class.
*
* @return the access flags
*/
public int getAccessFlags() {
return accessFlags;
}
/**
* Set the access flags of this class.
*
* @param accessFlags the access flags
*/
public void setAccessFlags(int accessFlags) {
this.accessFlags = accessFlags;
}
/**
* Get the constant pool index of this class.
*
* @return the index
*/
public int getThisClass() {
return thisClass;
}
/**
* Set the constant pool index of this class.
*
* @param thisClass the index
*/
public void setThisClass(int thisClass) {
this.thisClass = thisClass;
}
/**
* Get the name of this class.
*
* @return the name
* @throws InvalidByteCodeException
*/
public String getThisClassName() throws InvalidByteCodeException {
return getConstantPoolEntryName(getThisClass());
}
/**
* Get the constant pool index of the super class of this class.
*
* @return the index
*/
public int getSuperClass() {
return superClass;
}
/**
* Set the constant pool index of the super class of this class.
*
* @param superClass the index
*/
public void setSuperClass(int superClass) {
this.superClass = superClass;
}
/**
* Get the name of the super class.
*
* @return the name
* @throws InvalidByteCodeException
*/
public String getSuperClassName() throws InvalidByteCodeException {
return getConstantPoolEntryName(getSuperClass());
}
/**
* Get the array with the constant pool entries of all interfaces.
*
* @return the array
*/
public int[] getInterfaces() {
return interfaces;
}
/**
* Set the array with the constant pool entries of all interfaces.
*
* @param interfaces the array
*/
public void setInterfaces(int[] interfaces) {
this.interfaces = interfaces;
}
/**
* Get the array with the <tt>FieldInfo</tt> structures for the fields of this class.
*
* @return the array
*/
public FieldInfo[] getFields() {
return fields;
}
/**
* Set the array with the <tt>FieldInfo</tt> structures for the fields of this class.
*
* @param fields the array
*/
public void setFields(FieldInfo[] fields) {
this.fields = fields;
}
/**
* Get the array with the <tt>MethodInfo</tt> structures for the methods of this class.
*
* @return the array
*/
public MethodInfo[] getMethods() {
return methods;
}
/**
* Set the array with the <tt>MethodInfo</tt> structures for the methods of this class.
*
* @param methods the array
*/
public void setMethods(MethodInfo[] methods) {
this.methods = methods;
}
/**
* Get the the access flags of this class as a hex string.
*
* @return the hex string
*/
public String getFormattedAccessFlags() {
return printAccessFlags(accessFlags);
}
/**
* Get the verbose description of the access flags of this class.
*
* @return the description
*/
public String getAccessFlagsVerbose() {
return printAccessFlagsVerbose(accessFlags);
}
/**
* Get the <tt>ConstantUtf8Info</tt> constant pool entry at the specified index.
*
* @param index the index
* @return the constant pool entry
* @throws InvalidByteCodeException if the entry is not a <tt>ConstantUtf8Info</tt>
*/
public ConstantUtf8Info getConstantPoolUtf8Entry(int index)
throws InvalidByteCodeException {
return (ConstantUtf8Info)getConstantPoolEntry(index, ConstantUtf8Info.class);
}
/**
* Get the constant pool entry at the specified index.
*
* @param index the index
* @return the constant pool entry
* @throws InvalidByteCodeException if the entry is of a different class than expected
*/
public CPInfo getConstantPoolEntry(int index)
throws InvalidByteCodeException {
if (!checkValidConstantPoolIndex(index)) {
return null;
}
CPInfo cpInfo = constantPool[index];
return cpInfo;
}
/**
* Get the constant pool entry at the specified index and cast it to a specified class.
*
* @param index the index
* @param entryClass the required subtype of <tt>CPInfo</tt>
* @return the constant pool entry
* @throws InvalidByteCodeException if the entry is of a different class than expected
*/
public CPInfo getConstantPoolEntry(int index, Class entryClass)
throws InvalidByteCodeException {
if (!checkValidConstantPoolIndex(index)) {
return null;
}
CPInfo cpInfo = constantPool[index];
if (cpInfo == null) {
return null;
}
if (entryClass.isAssignableFrom(cpInfo.getClass())) {
return cpInfo;
} else {
throw new InvalidByteCodeException("constant pool entry at " + index +
" is not assignable to " +
entryClass.getName());
}
}
/**
* Get an approximate verbose description of the content of the constant pool entry
* at the specified index.
*
* @param index the index
* @return the description
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -