📄 classfile.java
字号:
/* JPC: A x86 PC Hardware Emulator for a pure Java Virtual Machine Release Version 2.0 A project from the Physics Dept, The University of Oxford Copyright (C) 2007 Isis Innovation Limited This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Details (including contact information) can be found at: www.physics.ox.ac.uk/jpc*/package org.jpc.classfile;
import java.io.*;
import java.lang.reflect.*;
import java.util.*;
public class ClassFile
{
private int magic;
private int minorVersion;
private int majorVersion;
private int constantPoolCount;
private ConstantPoolInfo[] constantPool;
private Map constantPoolMap;
private int accessFlags;
private int thisClass;
private int superClass;
private int interfacesCount;
private int[] interfaces;
private int fieldsCount;
private FieldInfo[] fields;
private int methodsCount;
private MethodInfo[] methods;
private int attributesCount;
private AttributeInfo[] attributes;
public static final short PUBLIC = (short) 0x0001;
public static final short FINAL = (short) 0x0010;
public static final short SUPER = (short) 0x0020;
public static final short INTERFACE = (short) 0x0200;
public static final short ABSTRACT = (short) 0x0400;
public static final int MAX_CONSTANT_POOL_SIZE = 64 * 1024;
public void read(DataInputStream in) throws IOException
{
readMagic(in);
// System.out.println("magic");
readVersion(in);
// System.out.println("version");
readConstantPool(in);
// System.out.println("constpool");
readAccessFlags(in);
// System.out.println("accflags");
readThisClass(in);
// System.out.println("thisclass");
readSuperClass(in);
// System.out.println("superclass");
readInterfaces(in);
// System.out.println("interfaces");
readFields(in, constantPool);
// System.out.println("fields");
readMethods(in, constantPool);
// System.out.println("methods");
readAttributes(in, constantPool);
// System.out.println("attributes");
return;
}
public void write(DataOutputStream out) throws IOException
{
writeMagic(out);
// System.out.println("magic");
writeVersion(out);
// System.out.println("version");
writeConstantPool(out);
// System.out.println("constpool");
writeAccessFlags(out);
// System.out.println("accflags");
writeThisClass(out);
// System.out.println("thisclass");
writeSuperClass(out);
// System.out.println("superclass");
writeInterfaces(out);
// System.out.println("interfaces");
writeFields(out);
// System.out.println("fields");
writeMethods(out);
// System.out.println("methods");
writeAttributes(out);
// System.out.println("attributes");
return;
}
public void update()
{
/* this function will supposibly sync all class info.
for now I am hoping that by changing to a lower version I can get
the class loader to ignore half my problems */
minorVersion = 0;
majorVersion = 46;
}
public String[] getMethodNames()
{
String[] names = new String[methodsCount];
for(int i = 0; (i < methodsCount); i++)
{
int index = methods[i].getNameIndex();
names[i] = ((ConstantPoolInfo.Utf8Info) constantPool[index]).getBytes();
}
return names;
}
public int[] getMethodCode(String methodName)
{
MethodInfo mi = getMethodInfo(methodName);
return mi.getCode();
}
public void setMethodCode(String methodName, int[] codeBytes)
{
setMethodCode(methodName, codeBytes, codeBytes.length);
}
public void setMethodCode(String methodName, int[] codeBytes, int codeBytesLength)
{
MethodInfo mi = getMethodInfo(methodName);
mi.setCode(codeBytes, codeBytesLength, this);
}
public AttributeInfo.CodeAttribute.ExceptionEntry[] getMethodExceptionTable(String methodName)
{
MethodInfo mi = getMethodInfo(methodName);
return mi.getExceptionTable();
}
public void setMethodExceptionTable(String methodName, AttributeInfo.CodeAttribute.ExceptionEntry[] exceptionTable)
{
setMethodExceptionTable(methodName, exceptionTable, exceptionTable.length);
}
public void setMethodExceptionTable(String methodName, AttributeInfo.CodeAttribute.ExceptionEntry[] exceptionTable, int exceptionTableLength)
{
MethodInfo mi = getMethodInfo(methodName);
mi.setExceptionTable(exceptionTable, exceptionTableLength, this);
}
public String getClassName()
{
if (constantPool[thisClass].getTag() != ConstantPoolInfo.CLASS)
throw new ClassFormatError("thisClass points to non-class constant pool entry");
int nameIndex = ((ConstantPoolInfo.ClassInfo) constantPool[thisClass]).getNameIndex();
if (constantPool[nameIndex].getTag() != ConstantPoolInfo.UTF8)
throw new ClassFormatError("thisClass constant pool entry points to non-utf8 constant pool entry");
return ((ConstantPoolInfo.Utf8Info) constantPool[nameIndex]).getBytes().replace('/','.');
}
public void setClassName(String name)
{
if (constantPool[thisClass].getTag() != ConstantPoolInfo.CLASS)
throw new ClassFormatError("thisClass points to non-class constant pool entry");
int nameIndex = ((ConstantPoolInfo.ClassInfo) constantPool[thisClass]).getNameIndex();
if (constantPool[nameIndex].getTag() != ConstantPoolInfo.UTF8)
throw new ClassFormatError("thisClass constant pool entry points to non-utf8 constant pool entry");
constantPool[nameIndex] = new ConstantPoolInfo.Utf8Info(name.replace('.','/'));
}
/** @return index into constant pool where value is stored */
public int addToConstantPool(Object o)
{
ConstantPoolInfo cpInfo = null;
if (o instanceof Field)
{
Field fld = (Field)o;
String descriptor = getDescriptor(fld.getType());
ConstantPoolInfo nameInfo = new ConstantPoolInfo.Utf8Info(fld.getName());
int nameIndex = addToConstantPool(nameInfo);
ConstantPoolInfo descriptorInfo = new ConstantPoolInfo.Utf8Info(descriptor);
int descriptorIndex = addToConstantPool(descriptorInfo);
ConstantPoolInfo nameAndTypeInfo = new ConstantPoolInfo.NameAndTypeInfo(nameIndex, descriptorIndex);
int nameAndTypeIndex = addToConstantPool(nameAndTypeInfo);
Class cls = ((Field)o).getDeclaringClass();
int classIndex = addToConstantPool(cls);
cpInfo = new ConstantPoolInfo.FieldRefInfo(classIndex, nameAndTypeIndex);
}
else if (o instanceof Method)
{
Method mtd = (Method)o;
Class[] params = mtd.getParameterTypes();
StringBuffer buf = new StringBuffer("(");
for (int i=0; i<params.length; i++)
buf.append(getDescriptor(params[i]));
buf.append(")");
buf.append(getDescriptor(mtd.getReturnType()));
String descriptor = buf.toString();
ConstantPoolInfo nameInfo = new ConstantPoolInfo.Utf8Info(mtd.getName());
int nameIndex = addToConstantPool(nameInfo);
ConstantPoolInfo descriptorInfo = new ConstantPoolInfo.Utf8Info(descriptor);
int descriptorIndex = addToConstantPool(descriptorInfo);
ConstantPoolInfo nameAndTypeInfo = new ConstantPoolInfo.NameAndTypeInfo(nameIndex, descriptorIndex);
int nameAndTypeIndex = addToConstantPool(nameAndTypeInfo);
Class cls = mtd.getDeclaringClass();
int classIndex = addToConstantPool(cls);
if (cls.isInterface())
cpInfo = new ConstantPoolInfo.InterfaceMethodRefInfo(classIndex, nameAndTypeIndex);
else
cpInfo = new ConstantPoolInfo.MethodRefInfo(classIndex, nameAndTypeIndex);
}
else if (o instanceof Class)
{
Class cls = (Class) o;
String className = cls.getName().replace('.','/');
cpInfo = new ConstantPoolInfo.Utf8Info(className);
int utf8Index = addToConstantPool(cpInfo);
cpInfo = new ConstantPoolInfo.ClassInfo(utf8Index);
}
else if (o instanceof String)
{
cpInfo = new ConstantPoolInfo.Utf8Info((String) o);
int utf8Index = addToConstantPool(cpInfo);
cpInfo = new ConstantPoolInfo.StringInfo(utf8Index);
}
else if (o instanceof Integer)
cpInfo = new ConstantPoolInfo.IntegerInfo(((Integer) o).intValue());
else if (o instanceof Float)
cpInfo = new ConstantPoolInfo.FloatInfo(((Float) o).floatValue());
else if (o instanceof Long)
cpInfo = new ConstantPoolInfo.LongInfo(((Long) o).longValue());
else if (o instanceof Double)
cpInfo = new ConstantPoolInfo.DoubleInfo(((Double) o).doubleValue());
else if (o instanceof ConstantPoolInfo)
cpInfo = (ConstantPoolInfo) o;
else
throw new IllegalArgumentException("Invalid Class To Add To Constant Pool");
int index = searchConstantPool(cpInfo);
if (index > 0)
return index;
if ((cpInfo instanceof ConstantPoolInfo.DoubleInfo) || (cpInfo instanceof ConstantPoolInfo.LongInfo)) {
constantPool[constantPoolCount] = cpInfo;
constantPoolMap.put(cpInfo, new Integer(constantPoolCount));
constantPool[constantPoolCount + 1] = cpInfo;
constantPoolCount += 2;
return constantPoolCount - 2;
} else {
constantPool[constantPoolCount] = cpInfo;
constantPoolMap.put(cpInfo, new Integer(constantPoolCount));
constantPoolCount++;
return constantPoolCount - 1;
}
}
public int getMethodMaxStack(String methodName)
{
MethodInfo mi = getMethodInfo(methodName);
return mi.getMaxStack();
}
public int getMethodMaxLocals(String methodName)
{
MethodInfo mi = getMethodInfo(methodName);
return mi.getMaxLocals();
}
protected String getConstantPoolFieldDescriptor(int index)
{
ConstantPoolInfo cpi = constantPool[index];
//get name and type index from method ref
index = ((ConstantPoolInfo.FieldRefInfo) cpi).getNameAndTypeIndex();
cpi = constantPool[index];
//get descriptor index from name and type
index = ((ConstantPoolInfo.NameAndTypeInfo) cpi).getDescriptorIndex();
cpi = constantPool[index];
return ((ConstantPoolInfo.Utf8Info) cpi).getBytes();
}
protected int getFieldLength(String fieldDescriptor)
{
return getFieldLength(fieldDescriptor.charAt(0));
}
private int getFieldLength(char ch)
{
switch(ch)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -