|
|
@@ -53,154 +53,132 @@ |
|
|
|
*/ |
|
|
|
package org.apache.tools.ant.taskdefs.optional.sitraka.bytecode; |
|
|
|
|
|
|
|
import java.io.DataInputStream; |
|
|
|
import java.io.IOException; |
|
|
|
import java.io.InputStream; |
|
|
|
import java.io.DataInputStream; |
|
|
|
|
|
|
|
import org.apache.tools.ant.taskdefs.optional.depend.constantpool.ConstantPool; |
|
|
|
import org.apache.tools.ant.taskdefs.optional.depend.constantpool.ClassCPInfo; |
|
|
|
import org.apache.tools.ant.taskdefs.optional.sitraka.bytecode.attributes.AttributeInfoList; |
|
|
|
import org.apache.tools.ant.taskdefs.optional.sitraka.bytecode.attributes.SourceFile; |
|
|
|
import org.apache.tools.ant.taskdefs.optional.depend.constantpool.ConstantPool; |
|
|
|
import org.apache.tools.ant.taskdefs.optional.depend.constantpool.Utf8CPInfo; |
|
|
|
import org.apache.tools.ant.taskdefs.optional.sitraka.bytecode.attributes.AttributeInfo; |
|
|
|
import org.apache.tools.ant.taskdefs.optional.sitraka.bytecode.attributes.SourceDir; |
|
|
|
import org.apache.tools.ant.taskdefs.optional.sitraka.bytecode.attributes.LineNumberTable; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* Object representing a class. |
|
|
|
* |
|
|
|
* Information are kept to the strict minimum for JProbe reports so |
|
|
|
* that not too many objects are created for a class, otherwise the |
|
|
|
* JVM can quickly run out of memory when analyzing a great deal of |
|
|
|
* classes and keeping them in memory for global analysis. |
|
|
|
* |
|
|
|
* @author <a href="sbailliez@imediation.com">Stephane Bailliez</a> |
|
|
|
*/ |
|
|
|
public class ClassFile { |
|
|
|
|
|
|
|
protected ConstantPool constantPool; |
|
|
|
|
|
|
|
protected InterfaceList interfaces; |
|
|
|
|
|
|
|
protected FieldInfoList fields; |
|
|
|
|
|
|
|
protected MethodInfoList methods; |
|
|
|
|
|
|
|
protected String sourceDir; |
|
|
|
|
|
|
|
protected String sourceFile; |
|
|
|
|
|
|
|
protected int access_flags; |
|
|
|
|
|
|
|
protected int this_class; |
|
|
|
|
|
|
|
protected int super_class; |
|
|
|
|
|
|
|
protected boolean isSynthetic; |
|
|
|
|
|
|
|
protected boolean isDeprecated; |
|
|
|
|
|
|
|
public ClassFile(InputStream is) throws IOException { |
|
|
|
DataInputStream dis = new DataInputStream(is); |
|
|
|
constantPool = new ConstantPool(); |
|
|
|
|
|
|
|
int magic = dis.readInt(); // 0xCAFEBABE |
|
|
|
int minor = dis.readShort(); |
|
|
|
int major = dis.readShort(); |
|
|
|
|
|
|
|
constantPool.read(dis); |
|
|
|
constantPool.resolve(); |
|
|
|
|
|
|
|
access_flags = dis.readShort(); |
|
|
|
this_class = dis.readShort(); |
|
|
|
super_class = dis.readShort(); |
|
|
|
|
|
|
|
interfaces = new InterfaceList(constantPool); |
|
|
|
interfaces.read(dis); |
|
|
|
//System.out.println(interfaces.toString()); |
|
|
|
|
|
|
|
fields = new FieldInfoList(constantPool); |
|
|
|
fields.read(dis); |
|
|
|
//System.out.println(fields.toString()); |
|
|
|
|
|
|
|
methods = new MethodInfoList(constantPool); |
|
|
|
methods.read(dis); |
|
|
|
//System.out.println(methods.toString()); |
|
|
|
|
|
|
|
AttributeInfoList attributes = new AttributeInfoList(constantPool); |
|
|
|
attributes.read(dis); |
|
|
|
SourceFile srcFile = (SourceFile)attributes.getAttribute(AttributeInfo.SOURCE_FILE); |
|
|
|
if (srcFile != null){ |
|
|
|
sourceFile = srcFile.getValue(); |
|
|
|
} |
|
|
|
SourceDir srcDir = (SourceDir)attributes.getAttribute(AttributeInfo.SOURCE_DIR); |
|
|
|
if (srcDir != null){ |
|
|
|
sourceDir = srcDir.getValue(); |
|
|
|
} |
|
|
|
isSynthetic = attributes.getAttribute(AttributeInfo.SYNTHETIC) != null; |
|
|
|
isDeprecated = attributes.getAttribute(AttributeInfo.DEPRECATED) != null; |
|
|
|
} |
|
|
|
|
|
|
|
public int getAccess(){ |
|
|
|
return access_flags; |
|
|
|
} |
|
|
|
public InterfaceList getInterfaces(){ |
|
|
|
return interfaces; |
|
|
|
} |
|
|
|
public String getSourceFile(){ |
|
|
|
return sourceFile; |
|
|
|
} |
|
|
|
public String getSourceDir(){ |
|
|
|
return sourceDir; |
|
|
|
} |
|
|
|
public boolean isSynthetic() { |
|
|
|
return isSynthetic; |
|
|
|
} |
|
|
|
public boolean isDeprecated() { |
|
|
|
return isDeprecated; |
|
|
|
} |
|
|
|
public MethodInfoList getMethods(){ |
|
|
|
return methods; |
|
|
|
} |
|
|
|
public FieldInfoList getFields(){ |
|
|
|
return fields; |
|
|
|
} |
|
|
|
public String getSuperName(){ |
|
|
|
return Utils.getUTF8Value(constantPool, super_class); |
|
|
|
} |
|
|
|
public String getFullName(){ |
|
|
|
return ((ClassCPInfo)constantPool.getEntry(this_class)).getClassName().replace('/','.'); |
|
|
|
} |
|
|
|
public String getName(){ |
|
|
|
String name = getFullName(); |
|
|
|
int pos = name.lastIndexOf('.'); |
|
|
|
if (pos == -1){ |
|
|
|
return ""; |
|
|
|
} |
|
|
|
return name.substring(pos + 1); |
|
|
|
} |
|
|
|
public String getPackage(){ |
|
|
|
String name = getFullName(); |
|
|
|
int pos = name.lastIndexOf('.'); |
|
|
|
if (pos == -1){ |
|
|
|
return ""; |
|
|
|
} |
|
|
|
return name.substring(0, pos); |
|
|
|
} |
|
|
|
|
|
|
|
/** dirty test method, move it into a testcase */ |
|
|
|
public static void main(String[] args) throws Exception { |
|
|
|
System.out.println("loading classfile..."); |
|
|
|
InputStream is = ClassLoader.getSystemResourceAsStream("java/util/Vector.class"); |
|
|
|
ClassFile clazzfile = new ClassFile(is); |
|
|
|
System.out.println("Class name: " + clazzfile.getName()); |
|
|
|
MethodInfoList methods = clazzfile.getMethods(); |
|
|
|
for (int i = 0; i < methods.length(); i++){ |
|
|
|
MethodInfo method = methods.getMethod(i); |
|
|
|
System.out.println("Method: " + method.getFullSignature()); |
|
|
|
System.out.println("line: " + method.getNumberOfLines()); |
|
|
|
LineNumberTable lnt = method.getCode().getLineNumberTable(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
public final class ClassFile { |
|
|
|
|
|
|
|
private MethodInfo[] methods; |
|
|
|
|
|
|
|
private String sourceFile; |
|
|
|
|
|
|
|
private String fullname; |
|
|
|
|
|
|
|
private int access_flags; |
|
|
|
|
|
|
|
public ClassFile(InputStream is) throws IOException { |
|
|
|
DataInputStream dis = new DataInputStream(is); |
|
|
|
ConstantPool constantPool = new ConstantPool(); |
|
|
|
|
|
|
|
int magic = dis.readInt(); // 0xCAFEBABE |
|
|
|
int minor = dis.readShort(); |
|
|
|
int major = dis.readShort(); |
|
|
|
|
|
|
|
constantPool.read(dis); |
|
|
|
constantPool.resolve(); |
|
|
|
|
|
|
|
// class information |
|
|
|
access_flags = dis.readShort(); |
|
|
|
int this_class = dis.readShort(); |
|
|
|
fullname = ((ClassCPInfo) constantPool.getEntry(this_class)).getClassName().replace('/', '.'); |
|
|
|
int super_class = dis.readShort(); |
|
|
|
|
|
|
|
// skip interfaces... |
|
|
|
int count = dis.readShort(); |
|
|
|
dis.skipBytes(count * 2); // short |
|
|
|
|
|
|
|
// skip fields... |
|
|
|
int numFields = dis.readShort(); |
|
|
|
for (int i = 0; i < numFields; i++) { |
|
|
|
// 3 short: access flags, name index, descriptor index |
|
|
|
dis.skip(2 * 3); |
|
|
|
// attribute list... |
|
|
|
int attributes_count = dis.readUnsignedShort(); |
|
|
|
for (int j = 0; j < attributes_count; j++) { |
|
|
|
dis.skipBytes(2); // skip attr_id (short) |
|
|
|
int len = dis.readInt(); |
|
|
|
dis.skipBytes(len); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// read methods |
|
|
|
int method_count = dis.readShort(); |
|
|
|
methods = new MethodInfo[method_count]; |
|
|
|
for (int i = 0; i < method_count; i++) { |
|
|
|
methods[i] = new MethodInfo(); |
|
|
|
methods[i].read(constantPool, dis); |
|
|
|
} |
|
|
|
|
|
|
|
// get interesting attributes. |
|
|
|
int attributes_count = dis.readUnsignedShort(); |
|
|
|
for (int j = 0; j < attributes_count; j++) { |
|
|
|
int attr_id = dis.readShort(); |
|
|
|
int len = dis.readInt(); |
|
|
|
String attr_name = Utils.getUTF8Value(constantPool, attr_id); |
|
|
|
if (AttributeInfo.SOURCE_FILE.equals(attr_name)) { |
|
|
|
int name_index = dis.readShort(); |
|
|
|
sourceFile = ((Utf8CPInfo) constantPool.getEntry(name_index)).getValue(); |
|
|
|
} else { |
|
|
|
dis.skipBytes(len); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
public int getAccess() { |
|
|
|
return access_flags; |
|
|
|
} |
|
|
|
|
|
|
|
public String getSourceFile() { |
|
|
|
return sourceFile; |
|
|
|
} |
|
|
|
|
|
|
|
public MethodInfo[] getMethods() { |
|
|
|
return methods; |
|
|
|
} |
|
|
|
|
|
|
|
public String getFullName() { |
|
|
|
return fullname; |
|
|
|
} |
|
|
|
|
|
|
|
public String getName() { |
|
|
|
String name = getFullName(); |
|
|
|
int pos = name.lastIndexOf('.'); |
|
|
|
if (pos == -1) { |
|
|
|
return ""; |
|
|
|
} |
|
|
|
return name.substring(pos + 1); |
|
|
|
} |
|
|
|
|
|
|
|
public String getPackage() { |
|
|
|
String name = getFullName(); |
|
|
|
int pos = name.lastIndexOf('.'); |
|
|
|
if (pos == -1) { |
|
|
|
return ""; |
|
|
|
} |
|
|
|
return name.substring(0, pos); |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|