Browse Source

Applied patch from Garrick Olson <garrick.olson@aceva.com>

I refactored the bytecode reading to avoid keeping unnecessary data and wasting memory.
I will do a second pass to remove all useless classes.


git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@269937 13f79535-47bb-0310-9956-ffa450edef68
master
Stephane Bailliez 23 years ago
parent
commit
c1b263f473
3 changed files with 722 additions and 744 deletions
  1. +497
    -508
      src/main/org/apache/tools/ant/taskdefs/optional/sitraka/XMLReport.java
  2. +111
    -133
      src/main/org/apache/tools/ant/taskdefs/optional/sitraka/bytecode/ClassFile.java
  3. +114
    -103
      src/main/org/apache/tools/ant/taskdefs/optional/sitraka/bytecode/MethodInfo.java

+ 497
- 508
src/main/org/apache/tools/ant/taskdefs/optional/sitraka/XMLReport.java
File diff suppressed because it is too large
View File


+ 111
- 133
src/main/org/apache/tools/ant/taskdefs/optional/sitraka/bytecode/ClassFile.java View File

@@ -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);
}

}






+ 114
- 103
src/main/org/apache/tools/ant/taskdefs/optional/sitraka/bytecode/MethodInfo.java View File

@@ -53,15 +53,11 @@
*/
package org.apache.tools.ant.taskdefs.optional.sitraka.bytecode;

import java.io.IOException;
import java.io.DataInputStream;
import java.io.IOException;

import org.apache.tools.ant.taskdefs.optional.depend.constantpool.ConstantPool;
import org.apache.tools.ant.taskdefs.optional.sitraka.bytecode.attributes.Code;
import org.apache.tools.ant.taskdefs.optional.sitraka.bytecode.attributes.Exceptions;
import org.apache.tools.ant.taskdefs.optional.sitraka.bytecode.attributes.AttributeInfoList;
import org.apache.tools.ant.taskdefs.optional.sitraka.bytecode.attributes.AttributeInfo;
import org.apache.tools.ant.taskdefs.optional.sitraka.bytecode.attributes.LineNumberTable;

/**
* Method info structure.
@@ -69,104 +65,119 @@ import org.apache.tools.ant.taskdefs.optional.sitraka.bytecode.attributes.LineNu
*
* @author <a href="sbailliez@imediation.com">Stephane Bailliez</a>
*/
public class MethodInfo {
protected ConstantPool constantPool;
protected int access_flags;
protected int name_index;
protected int descriptor_index;
protected Code code;
protected boolean deprecated;
protected boolean synthetic;
protected Exceptions exceptions;
public MethodInfo(ConstantPool pool){
constantPool = pool;
}
public void read(DataInputStream dis) throws IOException {
access_flags = dis.readShort();
name_index = dis.readShort();
descriptor_index = dis.readShort();
AttributeInfoList attrlist = new AttributeInfoList(constantPool);
attrlist.read(dis);
code = (Code)attrlist.getAttribute(AttributeInfo.CODE);
synthetic = attrlist.getAttribute(AttributeInfo.SYNTHETIC) != null;
deprecated = attrlist.getAttribute(AttributeInfo.DEPRECATED) != null;
exceptions = (Exceptions)attrlist.getAttribute(AttributeInfo.EXCEPTIONS);
}
public int getAccessFlags(){
return access_flags;
}
public String getName(){
return Utils.getUTF8Value(constantPool, name_index);
}
public String getDescriptor(){
return Utils.getUTF8Value(constantPool, descriptor_index);
}
public String getFullSignature(){
return getReturnType() + " " + getShortSignature();
}
public String getShortSignature(){
StringBuffer buf = new StringBuffer(getName());
buf.append("(");
String[] params = getParametersType();
for (int i = 0; i < params.length; i++){
buf.append(params[i]);
if (i != params.length - 1){
buf.append(", ");
}
}
buf.append(")");
return buf.toString();
}
public String getReturnType(){
return Utils.getMethodReturnType(getDescriptor());
}
public String[] getParametersType(){
return Utils.getMethodParams(getDescriptor());
}
public Code getCode(){
return code;
}
public int getNumberOfLines(){
int len = -1;
if (code != null){
LineNumberTable lnt = code.getLineNumberTable();
if (lnt != null){
len = lnt.length();
}
}
return len;
}
public boolean isDeprecated(){
return deprecated;
}
public boolean isSynthetic(){
return synthetic;
}
public String getAccess(){
return Utils.getMethodAccess(access_flags);
}
public String toString(){
StringBuffer sb = new StringBuffer();
sb.append("Method: ").append(getAccess()).append(" ");
sb.append(getFullSignature());
sb.append(" synthetic:").append(synthetic);
sb.append(" deprecated:").append(deprecated);
return sb.toString();
}
public final class MethodInfo {
private int access_flags;
private int loc = -1;
private String name;
private String descriptor;

public MethodInfo() {
}

public void read(ConstantPool constantPool, DataInputStream dis) throws IOException {
access_flags = dis.readShort();

int name_index = dis.readShort();
name = Utils.getUTF8Value(constantPool, name_index);

int descriptor_index = dis.readShort();
descriptor = Utils.getUTF8Value(constantPool, descriptor_index);

int attributes_count = dis.readUnsignedShort();
for (int i = 0; i < attributes_count; i++) {
int attr_id = dis.readShort();
String attr_name = Utils.getUTF8Value(constantPool, attr_id);
int len = dis.readInt();
if (AttributeInfo.CODE.equals(attr_name)) {
readCode(constantPool, dis);
} else {
dis.skipBytes(len);
}
}

}

protected void readCode(ConstantPool constantPool, DataInputStream dis) throws IOException {
// skip max_stack (short), max_local (short)
dis.skipBytes(2*2);

// skip bytecode...
int bytecode_len = dis.readInt();
dis.skip(bytecode_len);

// skip exceptions... 1 exception = 4 short.
int exception_count = dis.readShort();
dis.skipBytes(exception_count * 4 * 2);

// read attributes...
int attributes_count = dis.readUnsignedShort();
for (int i = 0; i < attributes_count; i++) {
int attr_id = dis.readShort();
String attr_name = Utils.getUTF8Value(constantPool, attr_id);
int len = dis.readInt();
if (AttributeInfo.LINE_NUMBER_TABLE.equals(attr_name)) {
// we're only interested in lines of code...
loc = dis.readShort();
// skip the table which is 2*loc*short
dis.skip(loc * 2 * 2);
} else {
dis.skipBytes(len);
}
}
}

public int getAccessFlags() {
return access_flags;
}

public String getName() {
return name;
}

public String getDescriptor() {
return descriptor;
}

public String getFullSignature() {
return getReturnType() + " " + getShortSignature();
}

public String getShortSignature() {
StringBuffer buf = new StringBuffer(getName());
buf.append("(");
String[] params = getParametersType();
for (int i = 0; i < params.length; i++) {
buf.append(params[i]);
if (i != params.length - 1) {
buf.append(", ");
}
}
buf.append(")");
return buf.toString();
}

public String getReturnType() {
return Utils.getMethodReturnType(getDescriptor());
}

public String[] getParametersType() {
return Utils.getMethodParams(getDescriptor());
}

public int getNumberOfLines() {
return loc;
}

public String getAccess() {
return Utils.getMethodAccess(access_flags);
}

public String toString() {
StringBuffer sb = new StringBuffer();
sb.append("Method: ").append(getAccess()).append(" ");
sb.append(getFullSignature());
return sb.toString();
}
}



Loading…
Cancel
Save