Browse Source

pr133532 fix: promoted compact representation to top level type - fixed memory leak when classes deleted

tags/REMOVING_ASM
aclement 17 years ago
parent
commit
a9744fe1e9

+ 36
- 119
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjState.java View File

@@ -40,15 +40,14 @@ import org.aspectj.org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
import org.aspectj.org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
import org.aspectj.org.eclipse.jdt.internal.compiler.env.IBinaryField;
import org.aspectj.org.eclipse.jdt.internal.compiler.env.IBinaryMethod;
import org.aspectj.org.eclipse.jdt.internal.compiler.env.IBinaryType;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.CompilerModifiers;
import org.aspectj.org.eclipse.jdt.internal.core.builder.ReferenceCollection;
import org.aspectj.org.eclipse.jdt.internal.core.builder.StringSet;
import org.aspectj.util.FileUtil;
import org.aspectj.weaver.BCException;
import org.aspectj.weaver.IWeaver;
import org.aspectj.weaver.ResolvedMember;
import org.aspectj.weaver.ResolvedType;
import org.aspectj.weaver.UnresolvedType;
import org.aspectj.weaver.bcel.BcelWeaver;
import org.aspectj.weaver.bcel.BcelWorld;
import org.aspectj.weaver.bcel.UnwovenClassFile;
@@ -162,6 +161,9 @@ public class AjState {
private List/*String*/ resources = new ArrayList();
private List/*String*/ aspectNames;
// these are references created on a particular compile run - when looping round in
// addAffectedSourceFiles(), if some have been created then we look at which source files
// touch upon those and get them recompiled.
private ArrayList/*<String>*/ qualifiedStrings;
private ArrayList/*<String>*/ simpleStrings;
@@ -278,6 +280,13 @@ public class AjState {
if (stateListener!=null) stateListener.detectedAspectDeleted(aDeletedFile);
return false;
}
List/*ClassFile*/ classes = (List)fullyQualifiedTypeNamesResultingFromCompilationUnit.get(aDeletedFile);
if (classes!=null) {
for (Iterator iterator = classes.iterator(); iterator.hasNext();) {
ClassFile element = (ClassFile) iterator.next();
resolvedTypeStructuresFromLastBuild.remove(element.fullyQualifiedTypeName);
}
}
}
return true;
}
@@ -617,6 +626,7 @@ public class AjState {
return ucf;
}
public void noteResult(InterimCompilationResult result) {
if (!maybeIncremental()) {
return;
@@ -770,7 +780,7 @@ public class AjState {
if (!rType.isMissing()) {
try {
ClassFileReader reader = new ClassFileReader(thisTime.getBytes(), null);
this.resolvedTypeStructuresFromLastBuild.put(thisTime.getClassName(),new CompactStructureRepresentation(reader));
this.resolvedTypeStructuresFromLastBuild.put(thisTime.getClassName(),new CompactTypeStructureRepresentation(reader));
} catch (ClassFormatException cfe) {
throw new BCException("Unexpected problem processing class",cfe);
}
@@ -778,12 +788,12 @@ public class AjState {
return;
}

CompactStructureRepresentation existingStructure = (CompactStructureRepresentation) this.resolvedTypeStructuresFromLastBuild.get(thisTime.getClassName());
CompactTypeStructureRepresentation existingStructure = (CompactTypeStructureRepresentation) this.resolvedTypeStructuresFromLastBuild.get(thisTime.getClassName());
ResolvedType newResolvedType = world.resolve(thisTime.getClassName());
if (!newResolvedType.isMissing()) {
try {
ClassFileReader reader = new ClassFileReader(thisTime.getBytes(), null);
this.resolvedTypeStructuresFromLastBuild.put(thisTime.getClassName(),new CompactStructureRepresentation(reader));
this.resolvedTypeStructuresFromLastBuild.put(thisTime.getClassName(),new CompactTypeStructureRepresentation(reader));
} catch (ClassFormatException cfe) {
throw new BCException("Unexpected problem processing class",cfe);
}
@@ -833,7 +843,7 @@ public class AjState {
* @param existingType
* @return
*/
private boolean hasStructuralChanges(ClassFileReader reader, CompactStructureRepresentation existingType) {
private boolean hasStructuralChanges(ClassFileReader reader, CompactTypeStructureRepresentation existingType) {
if (existingType == null) {
return true;
}
@@ -869,9 +879,9 @@ public class AjState {
}
// fields
MemberStructure[] existingFields = existingType.fields;
// CompactMemberStructureRepresentation[] existingFields = existingType.fields;
IBinaryField[] newFields = reader.getFields();
if (newFields == null) { newFields = new IBinaryField[0]; }
if (newFields == null) { newFields = CompactTypeStructureRepresentation.NoField; }

// all redundant for now ... could be an optimization at some point...
// remove any ajc$XXX fields from those we compare with
@@ -884,17 +894,18 @@ public class AjState {
// nonGenFields.add(field);
// //}
// }
if (newFields.length != existingFields.length) return true;
IBinaryField[] existingFs = existingType.binFields;
if (newFields.length != existingFs.length) return true;
new_field_loop:
for (int i = 0; i < newFields.length; i++) {
IBinaryField field = newFields[i];
char[] fieldName = field.getName();
for (int j = 0; j < existingFields.length; j++) {
if (CharOperation.equals(existingFields[j].name,fieldName)) {
if (!modifiersEqual(field.getModifiers(),existingFields[j].modifiers)) {
for (int j = 0; j < existingFs.length; j++) {
if (CharOperation.equals(existingFs[j].getName(),fieldName)) {
if (!modifiersEqual(field.getModifiers(),existingFs[j].getModifiers())) {
return true;
}
if (!CharOperation.equals(existingFields[j].signature,field.getTypeName())) {
if (!CharOperation.equals(existingFs[j].getTypeName(),field.getTypeName())) {
return true;
}
continue new_field_loop;
@@ -904,9 +915,9 @@ public class AjState {
}
// methods
MemberStructure[] existingMethods = existingType.methods;
// CompactMemberStructureRepresentation[] existingMethods = existingType.methods;
IBinaryMethod[] newMethods = reader.getMethods();
if (newMethods == null) { newMethods = new IBinaryMethod[0]; }
if (newMethods == null) { newMethods = CompactTypeStructureRepresentation.NoMethod; }
// all redundant for now ... could be an optimization at some point...
@@ -944,15 +955,16 @@ public class AjState {
// nonGenMethods.add(method);
//// }
// }
if (newMethods.length != existingMethods.length) return true;
IBinaryMethod[] existingMs = existingType.binMethods;
if (newMethods.length != existingMs.length) return true;
new_method_loop:
for (int i = 0; i < newMethods.length; i++) {
IBinaryMethod method = newMethods[i];
char[] methodName = method.getSelector();
for (int j = 0; j < existingMethods.length; j++) {
if (CharOperation.equals(existingMethods[j].name,methodName)) {
for (int j = 0; j < existingMs.length; j++) {
if (CharOperation.equals(existingMs[j].getSelector(),methodName)) {
// candidate match
if (!CharOperation.equals(method.getMethodDescriptor(),existingMethods[j].signature)) {
if (!CharOperation.equals(method.getMethodDescriptor(),existingMs[j].getMethodDescriptor())) {
// ok, the descriptors don't match, but is this a funky ctor on a non-static inner
// type?
// boolean mightBeOK =
@@ -973,7 +985,7 @@ public class AjState {
continue; // might be overloading
} else {
// matching sigs
if (!modifiersEqual(method.getModifiers(),existingMethods[j].modifiers)) {
if (!modifiersEqual(method.getModifiers(),existingMs[j].getModifiers())) {
return true;
}
continue new_method_loop;
@@ -1230,105 +1242,6 @@ public class AjState {
}
}

private static class CompactStructureRepresentation {
char[] className;
int modifiers;
char[] genericSignature;
char[] superclassName;
char[][] interfaces;
MemberStructure[] fields;
MemberStructure[] methods;
public CompactStructureRepresentation(ClassFileReader cfr) {
this.className = cfr.getName(); // slashes...
this.modifiers = cfr.getModifiers();
this.genericSignature = cfr.getGenericSignature();
// if (this.genericSignature.length == 0) {
// this.genericSignature = null;
// }
this.superclassName = cfr.getSuperclassName(); // slashes...
interfaces = cfr.getInterfaceNames();

IBinaryField[] rFields = cfr.getFields();
this.fields = new MemberStructure[rFields==null?0:rFields.length];
if (rFields!=null) {
for (int i = 0; i < rFields.length; i++) {
this.fields[i] = new MemberStructure();
this.fields[i].name = rFields[i].getName();
this.fields[i].modifiers = rFields[i].getModifiers();
this.fields[i].signature = rFields[i].getTypeName();
}
}
IBinaryMethod[] rMethods = cfr.getMethods();
this.methods = new MemberStructure[rMethods==null?0:rMethods.length];
if (rMethods!=null) {
for (int i = 0; i < rMethods.length; i++) {
this.methods[i] = new MemberStructure();
this.methods[i].name = rMethods[i].getSelector();
this.methods[i].modifiers = rMethods[i].getModifiers();
// StringBuffer sig = new StringBuffer();
// sig.append("(");
// UnresolvedType[] pTypes = rMethods[i].getMethodDescriptor();
// for (int j = 0; j < pTypes.length; j++) {
// sig.append(pTypes[j].getSignature());
// }
// sig.append(")");
// sig.append(rMethods[i].getReturnType().getSignature());
this.methods[i].signature =rMethods[i].getMethodDescriptor();// sig.toString().toCharArray();
}
}
}
public CompactStructureRepresentation(ResolvedType forType) {
this.className = forType.getName().replace('.','/').toCharArray();
this.modifiers = forType.getModifiers();
this.genericSignature = forType.getGenericSignature().toCharArray();
if (this.genericSignature.length == 0) {
this.genericSignature = null;
}
this.superclassName = forType.getSuperclass().getName().replace('.','/').toCharArray();
ResolvedType[] rTypes = forType.getDeclaredInterfaces();
this.interfaces = new char[rTypes.length][];
for (int i = 0; i < rTypes.length; i++) {
this.interfaces[i] = rTypes[i].getName().replace('.','/').toCharArray();
}
ResolvedMember[] rFields = forType.getDeclaredFields();
this.fields = new MemberStructure[rFields.length];
for (int i = 0; i < rFields.length; i++) {
this.fields[i] = new MemberStructure();
this.fields[i].name = rFields[i].getName().toCharArray();
this.fields[i].modifiers = rFields[i].getModifiers();
this.fields[i].signature = rFields[i].getReturnType().getSignature().toCharArray();
}
ResolvedMember[] rMethods = forType.getDeclaredMethods();
this.methods = new MemberStructure[rMethods.length];
for (int i = 0; i < rMethods.length; i++) {
this.methods[i] = new MemberStructure();
this.methods[i].name = rMethods[i].getName().toCharArray();
this.methods[i].modifiers = rMethods[i].getModifiers();
StringBuffer sig = new StringBuffer();
sig.append("(");
UnresolvedType[] pTypes = rMethods[i].getParameterTypes();
for (int j = 0; j < pTypes.length; j++) {
sig.append(pTypes[j].getSignature());
}
sig.append(")");
sig.append(rMethods[i].getReturnType().getSignature());
this.methods[i].signature = sig.toString().toCharArray();
}
}
}
private static class MemberStructure {
char[] name;
int modifiers;
char[] signature;
}
public void wipeAllKnowledge() {
buildManager.state = null;
buildManager.setStructureModel(null);
@@ -1350,4 +1263,8 @@ public class AjState {
public IStateListener getListener() {
return stateListener;
}

public IBinaryType checkPreviousBuild(String name) {
return (IBinaryType)resolvedTypeStructuresFromLastBuild.get(name);
}
}

Loading…
Cancel
Save