summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoracolyer <acolyer>2006-02-24 12:35:43 +0000
committeracolyer <acolyer>2006-02-24 12:35:43 +0000
commit5be99e59411e13ed9e779c96811d4d4ca947fe94 (patch)
tree75f553bbda6ea54ef0f40f8bc9761535505f9fad
parentd667d9eeb975c3de1953e5057209dee451b62231 (diff)
downloadaspectj-5be99e59411e13ed9e779c96811d4d4ca947fe94.tar.gz
aspectj-5be99e59411e13ed9e779c96811d4d4ca947fe94.zip
Completed: Improve ajc memory usage
the last of the big memory hog in AjState is now removed.
-rw-r--r--org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildManager.java5
-rw-r--r--org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjState.java403
-rw-r--r--org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/StatefulNameEnvironment.java42
3 files changed, 311 insertions, 139 deletions
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildManager.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildManager.java
index 1ef198bf2..4f6c664c7 100644
--- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildManager.java
+++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildManager.java
@@ -234,6 +234,7 @@ public class AjBuildManager implements IOutputClassFileNameProvider,IBinarySourc
}
binarySourcesForTheNextCompile = state.getBinaryFilesToCompile(true);
performCompilation(buildConfig.getFiles());
+ state.clearBinarySourceFiles(); // we don't want these hanging around...
if (handler.hasErrors()) {
CompilationAndWeavingContext.leavingPhase(ct);
return false;
@@ -815,8 +816,8 @@ public class AjBuildManager implements IOutputClassFileNameProvider,IBinarySourc
//System.out.println("compiling");
environment = getLibraryAccess(classpaths, filenames);
- if (!state.getClassNameToUCFMap().isEmpty()) {
- environment = new StatefulNameEnvironment(environment, state.getClassNameToUCFMap());
+ if (!state.getClassNameToFileMap().isEmpty()) {
+ environment = new StatefulNameEnvironment(environment, state.getClassNameToFileMap());
}
org.aspectj.ajdt.internal.compiler.CompilerAdapter.setCompilerAdapterFactory(this);
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjState.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjState.java
index e47215ace..e901f057e 100644
--- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjState.java
+++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjState.java
@@ -23,6 +23,7 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -36,11 +37,19 @@ import org.aspectj.bridge.SourceLocation;
import org.aspectj.org.eclipse.jdt.internal.compiler.CompilationResult;
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.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.org.eclipse.jdt.internal.core.util.Util;
import org.aspectj.util.FileUtil;
import org.aspectj.weaver.IWeaver;
+import org.aspectj.weaver.ReferenceType;
+import org.aspectj.weaver.ReferenceTypeDelegate;
+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;
@@ -71,7 +80,8 @@ public class AjState {
/**
* Keeps a list of (FQN,Filename) pairs (as ClassFile objects)
* for types that resulted from the compilation of the given
- * File.
+ * File. Note :- the ClassFile objects contain no byte code,
+ * they are simply a Filename,typename pair.
*
* Populated in noteResult and used in addDependentsOf(File)
*
@@ -86,7 +96,7 @@ public class AjState {
*
* Added by AMC during state refactoring, 1Q06.
*/
- private Set sourceFilesDefiningAspects = new HashSet();
+ private Set/*<File>*/ sourceFilesDefiningAspects = new HashSet();
/**
* Populated in noteResult to record the set of types that should be recompiled if
@@ -99,7 +109,9 @@ public class AjState {
/**
* Holds UnwovenClassFiles (byte[]s) originating from the given file source. This
* could be a jar file, a directory, or an individual .class file. This is an
- * *expensive* map we would like to release much earlier if possible.
+ * *expensive* map. It is cleared immediately following a batch build, and the
+ * cheaper inputClassFilesBySource map is kept for processing of any subsequent
+ * incremental builds.
*
* Populated during AjBuildManager.initBcelWorld().
*
@@ -116,11 +128,24 @@ public class AjState {
*
*/
private Map/*File, List<UnwovenClassFile>*/ binarySourceFiles = new HashMap();
+
+ /**
+ * Initially a duplicate of the information held in binarySourceFiles, with the
+ * key difference that the values are ClassFiles (type name, File) not UnwovenClassFiles
+ * (which also have all the byte code in them). After a batch build, binarySourceFiles
+ * is cleared, leaving just this much lighter weight map to use in processing
+ * subsequent incremental builds.
+ */
+ private Map/*<File,List<ClassFile>*/ inputClassFilesBySource = new HashMap();
+
+ /**
+ * Holds structure information on types as they were at the end of the last
+ * build. It would be nice to get rid of this too, but can't see an easy way to do
+ * that right now.
+ */
+ private Map/*FQN,CompactStructureRepresentation*/ resolvedTypeStructuresFromLastBuild = new HashMap();
/**
- * The third of the three expensive collections of state held by AjState to support
- * incremental compilation. FQN -> UCF.
- *
* Populated in noteResult to record the set of UnwovenClassFiles (intermediate results)
* that originated from compilation of the class with the given fully-qualified name.
*
@@ -129,7 +154,7 @@ public class AjState {
* Passed into StatefulNameEnvironment during incremental compilation to support
* findType lookups.
*/
- private Map/*<String, UnwovenClassFile>*/ classesFromName = new HashMap();
+ private Map/*<String, File>*/ classesFromName = new HashMap();
private List/*File*/ compiledSourceFiles = new ArrayList();
@@ -319,7 +344,7 @@ public class AjState {
* lastSBT is the last build time for the state asking the question
*/
private boolean hasStructuralChangedSince(File file,long lastSuccessfulBuildTime) {
- long lastModTime = file.lastModified();
+ //long lastModTime = file.lastModified();
Long l = (Long)structuralChangesSinceLastFullBuild.get(file.getAbsolutePath());
long strucModTime = -1;
if (l!=null) strucModTime = l.longValue();
@@ -426,6 +451,9 @@ public class AjState {
ucfs.add(ucf);
addDependentsOf(ucf.getClassName());
binarySourceFiles.put(bsf.binSrc.getPath(),ucfs);
+ List cfs = new ArrayList(1);
+ cfs.add(getClassFileFor(ucf));
+ this.inputClassFilesBySource.put(bsf.binSrc.getPath(), cfs);
toWeave.put(bsf.binSrc.getPath(),ucfs);
}
deleteBinaryClassFiles();
@@ -441,20 +469,16 @@ public class AjState {
*/
private void removeAllResultsOfLastBuild() {
// remove all binarySourceFiles, and all classesFromName...
- for (Iterator iter = binarySourceFiles.values().iterator(); iter.hasNext();) {
- List ucfs = (List) iter.next();
- for (Iterator iterator = ucfs.iterator(); iterator.hasNext();) {
- UnwovenClassFile ucf = (UnwovenClassFile) iterator.next();
- try {
- ucf.deleteRealFile();
- } catch (IOException ex) { /* we did our best here */ }
+ for (Iterator iter = this.inputClassFilesBySource.values().iterator(); iter.hasNext();) {
+ List cfs = (List) iter.next();
+ for (Iterator iterator = cfs.iterator(); iterator.hasNext();) {
+ ClassFile cf = (ClassFile) iterator.next();
+ cf.deleteFromFileSystem();
}
}
for (Iterator iterator = classesFromName.values().iterator(); iterator.hasNext();) {
- UnwovenClassFile ucf = (UnwovenClassFile) iterator.next();
- try {
- ucf.deleteRealFile();
- } catch (IOException ex) { /* we did our best here */ }
+ File f = (File) iterator.next();
+ new ClassFile("",f).deleteFromFileSystem();
}
for (Iterator iter = resources.iterator(); iter.hasNext();) {
String resource = (String) iter.next();
@@ -484,15 +508,11 @@ public class AjState {
// range of bsf is ucfs, domain is files (.class and jars) in inpath/jars
for (Iterator iter = deletedBinaryFiles.iterator(); iter.hasNext();) {
AjBuildConfig.BinarySourceFile deletedFile = (AjBuildConfig.BinarySourceFile) iter.next();
- List ucfs = (List) binarySourceFiles.get(deletedFile.binSrc.getPath());
- binarySourceFiles.remove(deletedFile.binSrc.getPath());
-
- // AMC temp during refactoring
- UnwovenClassFile ucf = (UnwovenClassFile) ucfs.get(0);
- ClassFile cf = new ClassFile(ucf.getClassName(),new File(ucf.getFilename()));
- // end temp
-
- deleteClassFile(cf);
+ List cfs = (List) this.inputClassFilesBySource.get(deletedFile.binSrc.getPath());
+ for (Iterator iterator = cfs.iterator(); iterator.hasNext();) {
+ deleteClassFile((ClassFile)iterator.next());
+ }
+ this.inputClassFilesBySource.remove(deletedFile.binSrc.getPath());
}
}
@@ -584,9 +604,9 @@ public class AjState {
UnwovenClassFile[] unwovenClassFiles = result.unwovenClassFiles();
for (int i = 0; i < unwovenClassFiles.length; i++) {
- UnwovenClassFile lastTimeRound = (UnwovenClassFile) classesFromName.get(unwovenClassFiles[i].getClassName());
+ File lastTimeRound = (File) classesFromName.get(unwovenClassFiles[i].getClassName());
recordClassFile(unwovenClassFiles[i],lastTimeRound);
- classesFromName.put(unwovenClassFiles[i].getClassName(),unwovenClassFiles[i]);
+ classesFromName.put(unwovenClassFiles[i].getClassName(),new File(unwovenClassFiles[i].getFilename()));
}
// need to do this before types are deleted from the World...
@@ -713,111 +733,176 @@ public class AjState {
return null;
}
- private void recordClassFile(UnwovenClassFile thisTime, UnwovenClassFile lastTime) {
- if (simpleStrings == null) return; // batch build
+ private void recordClassFile(UnwovenClassFile thisTime, File lastTime) {
+ if (simpleStrings == null) {
+ // batch build
+ // record resolved type for structural comparisions in future increments
+ // this records a second reference to a structure already held in memory
+ // by the world.
+ ResolvedType rType = world.resolve(thisTime.getClassName());
+ if (!rType.isMissing()) {
+ this.resolvedTypeStructuresFromLastBuild.put(thisTime.getClassName(),new CompactStructureRepresentation(rType));
+ }
+ return;
+ }
+ CompactStructureRepresentation existingStructure = (CompactStructureRepresentation) this.resolvedTypeStructuresFromLastBuild.get(thisTime.getClassName());
+ ReferenceType newResolvedType = (ReferenceType) world.resolve(thisTime.getClassName());
+ if (!newResolvedType.isMissing()) {
+ this.resolvedTypeStructuresFromLastBuild.put(thisTime.getClassName(),new CompactStructureRepresentation(newResolvedType));
+ }
+
if (lastTime == null) {
addDependentsOf(thisTime.getClassName());
return;
}
- byte[] newBytes = thisTime.getBytes();
- byte[] oldBytes = lastTime.getBytes();
- boolean bytesEqual = (newBytes.length == oldBytes.length);
- for (int i = 0; (i < oldBytes.length) && bytesEqual; i++) {
- if (newBytes[i] != oldBytes[i]) bytesEqual = false;
+ if (newResolvedType.isMissing()) {
+ return;
}
- if (!bytesEqual) {
- try {
- ClassFileReader reader = new ClassFileReader(oldBytes, lastTime.getFilename().toCharArray());
- // ignore local types since they're only visible inside a single method
- if (!(reader.isLocal() || reader.isAnonymous()) &&
- reader.hasStructuralChanges(newBytes)) {
+
+ byte[] newBytes = thisTime.getBytes();
+ try {
+ ClassFileReader reader = new ClassFileReader(newBytes, lastTime.getAbsolutePath().toCharArray());
+ // ignore local types since they're only visible inside a single method
+ if (!(reader.isLocal() || reader.isAnonymous())) {
+ if (hasStructuralChanges(reader,existingStructure)) {
structuralChangesSinceLastFullBuild.put(thisTime.getFilename(),new Long(currentBuildTime));
- addDependentsOf(lastTime.getClassName());
+ addDependentsOf(new String(reader.getName()).replace('/','.'));
}
- } catch (ClassFormatException e) {
- addDependentsOf(lastTime.getClassName());
- }
- }
+ }
+ } catch (ClassFormatException e) {
+ addDependentsOf(thisTime.getClassName());
+ }
}
+
+ /**
+ * Compare the class structure of the new intermediate (unwoven) class with the
+ * existingResolvedType of the same class that we have in the world, looking for
+ * any structural differences (and ignoring aj members resulting from weaving....)
+ *
+ * Warning : long but boring method implementation...
+ * @param reader
+ * @param existingType
+ * @return
+ */
+ private boolean hasStructuralChanges(ClassFileReader reader, CompactStructureRepresentation existingType) {
+ // mirrors the checks in ClassFileReader.hasStructuralChanges, but compares against
+ // ref type delegate instead of old bytes
+ if (existingType == null) {
+ return true;
+ }
+
+ // modifiers
+ if (!modifiersEqual(reader.getModifiers(),existingType.modifiers)) {
+ return true;
+ }
+
+ // generic signature
+ if (!equal(reader.getGenericSignature(),existingType.genericSignature)) {
+ return true;
+ }
+
+ // superclass name
+ if (!equal(reader.getSuperclassName(),existingType.superclassName)) {
+ return true;
+ }
+
+ // interfaces
+ char[][] existingIfs = existingType.interfaces;
+ char[][] newIfsAsChars = reader.getInterfaceNames();
+ if (newIfsAsChars == null) { newIfsAsChars = new char[0][]; }
+ char[][] newIfs = new char[newIfsAsChars.length][];
+ if (existingIfs.length != newIfs.length) {
+ return true;
+ }
+ new_interface_loop: for (int i = 0; i < newIfs.length; i++) {
+ for (int j = 0; j < existingIfs.length; j++) {
+ if (equal(existingIfs[j],newIfs[i])) {
+ continue new_interface_loop;
+ }
+ }
+ return true;
+ }
+
+ // fields
+ MemberStructure[] existingFields = existingType.fields;
+ IBinaryField[] newFields = reader.getFields();
+ if (newFields == null) { newFields = new IBinaryField[0]; }
+ if (newFields.length != existingFields.length) {
+ return true;
+ }
+ new_field_loop: for (int i = 0; i < newFields.length; i++) {
+ char[] fieldName = newFields[i].getName();
+ for (int j = 0; j < existingFields.length; j++) {
+ if (equal(existingFields[j].name,fieldName)) {
+ if (!modifiersEqual(newFields[i].getModifiers(),existingFields[j].modifiers)) {
+ return true;
+ }
+ if (!equal(existingFields[j].signature,newFields[i].getTypeName())) {
+ return true;
+ }
+ continue new_field_loop;
+ }
+ }
+ return true;
+ }
+
+ // methods
+ MemberStructure[] existingMethods = existingType.methods;
+ IBinaryMethod[] newMethods = reader.getMethods();
+ if (newMethods == null) { newMethods = new IBinaryMethod[0]; }
+ if (newMethods.length != existingMethods.length) {
+ return true;
+ }
+ new_method_loop: for (int i = 0; i < newMethods.length; i++) {
+ char[] methodName = newMethods[i].getSelector();
+ for (int j = 0; j < existingMethods.length; j++) {
+ if (equal(existingMethods[j].name,methodName)) {
+ // candidate match
+ if (!equal(newMethods[i].getMethodDescriptor(),existingMethods[j].signature)) {
+ continue; // might be overloading
+ }
+ else {
+ // matching sigs
+ if (!modifiersEqual(newMethods[i].getModifiers(),existingMethods[j].modifiers)) {
+ return true;
+ }
+ continue new_method_loop;
+ }
+ }
+ }
+ return true; // (no match found)
+ }
+
+ return false;
+ }
-// public void noteClassesFromFile(CompilationResult result, String sourceFileName, List unwovenClassFiles) {
-// File sourceFile = new File(sourceFileName);
-//
-// if (result != null) {
-// references.put(sourceFile, new ReferenceCollection(result.qualifiedReferences, result.simpleNameReferences));
-// }
-//
-// List previous = (List)classesFromFile.get(sourceFile);
-// List newClassFiles = new ArrayList();
-// for (Iterator i = unwovenClassFiles.iterator(); i.hasNext();) {
-// UnwovenClassFile cf = (UnwovenClassFile) i.next();
-// cf = writeClassFile(cf, findAndRemoveClassFile(cf.getClassName(), previous));
-// newClassFiles.add(cf);
-// classesFromName.put(cf.getClassName(), cf);
-// }
-//
-// if (previous != null && !previous.isEmpty()) {
-// for (Iterator i = previous.iterator(); i.hasNext();) {
-// UnwovenClassFile cf = (UnwovenClassFile) i.next();
-// deleteClassFile(cf);
-// }
-// }
-//
-// classesFromFile.put(sourceFile, newClassFiles);
-// resultsFromFile.put(sourceFile, result);
-// }
-//
-// private UnwovenClassFile findAndRemoveClassFile(String name, List previous) {
-// if (previous == null) return null;
-// for (Iterator i = previous.iterator(); i.hasNext();) {
-// UnwovenClassFile cf = (UnwovenClassFile) i.next();
-// if (cf.getClassName().equals(name)) {
-// i.remove();
-// return cf;
-// }
-// }
-// return null;
-// }
-//
-// private UnwovenClassFile writeClassFile(UnwovenClassFile cf, UnwovenClassFile previous) {
-// if (simpleStrings == null) { // batch build
-// addedClassFiles.add(cf);
-// return cf;
-// }
-//
-// try {
-// if (previous == null) {
-// addedClassFiles.add(cf);
-// addDependentsOf(cf.getClassName());
-// return cf;
-// }
-//
-// byte[] oldBytes = previous.getBytes();
-// byte[] newBytes = cf.getBytes();
-// //if (this.compileLoop > 1) { // only optimize files which were recompiled during the dependent pass, see 33990
-// notEqual : if (newBytes.length == oldBytes.length) {
-// for (int i = newBytes.length; --i >= 0;) {
-// if (newBytes[i] != oldBytes[i]) break notEqual;
-// }
-// //addedClassFiles.add(previous); //!!! performance wasting
-// buildManager.bcelWorld.addSourceObjectType(previous.getJavaClass());
-// return previous; // bytes are identical so skip them
-// }
-// //}
-// ClassFileReader reader = new ClassFileReader(oldBytes, previous.getFilename().toCharArray());
-// // ignore local types since they're only visible inside a single method
-// if (!(reader.isLocal() || reader.isAnonymous()) && reader.hasStructuralChanges(newBytes)) {
-// addDependentsOf(cf.getClassName());
-// }
-// } catch (ClassFormatException e) {
-// addDependentsOf(cf.getClassName());
-// }
-// addedClassFiles.add(cf);
-// return cf;
-// }
+ private boolean modifiersEqual(int eclipseModifiers, int resolvedTypeModifiers) {
+ resolvedTypeModifiers = resolvedTypeModifiers & CompilerModifiers.AccJustFlag;
+ eclipseModifiers = eclipseModifiers & CompilerModifiers.AccJustFlag;
+ if ((eclipseModifiers & CompilerModifiers.AccSuper) != 0) {
+ eclipseModifiers -= CompilerModifiers.AccSuper;
+ }
+ return (eclipseModifiers == resolvedTypeModifiers);
+ }
+
+ private boolean equal(char[] c1, char[] c2) {
+ if (c1 == null && c2 == null) {
+ return true;
+ }
+ if (c1 == null || c2 == null) {
+ return false;
+ }
+ if (c1.length != c2.length) {
+ return false;
+ }
+ for (int i = 0; i < c1.length; i++) {
+ if (c1[i] != c2[i]) return false;
+ }
+ return true;
+ }
private static StringSet makeStringSet(List strings) {
StringSet ret = new StringSet(strings.size());
@@ -943,13 +1028,28 @@ public class AjState {
public void recordBinarySource(String fromPathName, List unwovenClassFiles) {
this.binarySourceFiles.put(fromPathName,unwovenClassFiles);
+ List simpleClassFiles = new LinkedList();
+ for (Iterator iter = unwovenClassFiles.iterator(); iter.hasNext();) {
+ UnwovenClassFile ucf = (UnwovenClassFile) iter.next();
+ ClassFile cf = getClassFileFor(ucf);
+ simpleClassFiles.add(cf);
+ }
+ this.inputClassFilesBySource.put(fromPathName,simpleClassFiles);
+ }
+
+ /**
+ * @param ucf
+ * @return
+ */
+ private ClassFile getClassFileFor(UnwovenClassFile ucf) {
+ return new ClassFile(ucf.getClassName(),new File(ucf.getFilename()));
}
public Map getBinarySourceMap() {
return this.binarySourceFiles;
}
- public Map getClassNameToUCFMap() {
+ public Map getClassNameToFileMap() {
return this.classesFromName;
}
@@ -1012,4 +1112,59 @@ public class AjState {
}
}
+ private static class CompactStructureRepresentation {
+
+ 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();
+ }
+ }
+
+ char[] className;
+ int modifiers;
+ char[] genericSignature;
+ char[] superclassName;
+ char[][] interfaces;
+ MemberStructure[] fields;
+ MemberStructure[] methods;
+ }
+
+ private static class MemberStructure {
+ char[] name;
+ int modifiers;
+ char[] signature;
+ }
}
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/StatefulNameEnvironment.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/StatefulNameEnvironment.java
index 8d00916d8..11524e9e8 100644
--- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/StatefulNameEnvironment.java
+++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/StatefulNameEnvironment.java
@@ -14,27 +14,32 @@
package org.aspectj.ajdt.internal.core.builder;
//import java.util.HashMap;
+import java.io.File;
+import java.io.IOException;
import java.util.Collections;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
-import org.aspectj.weaver.bcel.UnwovenClassFile;
import org.aspectj.org.eclipse.jdt.core.compiler.CharOperation;
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.INameEnvironment;
import org.aspectj.org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
+import org.aspectj.util.FileUtil;
public class StatefulNameEnvironment implements INameEnvironment {
private Map classesFromName;
+ private Map inflatedClassFilesCache;
private Set packageNames;
private INameEnvironment baseEnvironment;
public StatefulNameEnvironment(INameEnvironment baseEnvironment, Map classesFromName) {
this.classesFromName = classesFromName;
+ this.inflatedClassFilesCache = new HashMap();
this.baseEnvironment = baseEnvironment;
packageNames = new HashSet();
@@ -60,18 +65,29 @@ public class StatefulNameEnvironment implements INameEnvironment {
}
private NameEnvironmentAnswer findType(String name) {
- UnwovenClassFile cf = (UnwovenClassFile)classesFromName.get(name);
- //System.err.println("find: " + name + " found: " + cf);
-
- if (cf == null) return null;
-
- try {
- //System.out.println("from cache: " + name);
- return new NameEnvironmentAnswer(
- new ClassFileReader(cf.getBytes(), cf.getFilename().toCharArray()),
- null /* no access restriction */);
- } catch (ClassFormatException e) {
- return null; //!!! seems to match FileSystem behavior
+ if (this.inflatedClassFilesCache.containsKey(name)) {
+ return (NameEnvironmentAnswer) this.inflatedClassFilesCache.get(name);
+ }
+ else {
+ File fileOnDisk = (File)classesFromName.get(name);
+ //System.err.println("find: " + name + " found: " + cf);
+
+ if (fileOnDisk == null) return null;
+
+ try {
+ //System.out.println("from cache: " + name);
+ byte[] bytes = FileUtil.readAsByteArray(fileOnDisk);
+ NameEnvironmentAnswer ret =
+ new NameEnvironmentAnswer(
+ new ClassFileReader(bytes, fileOnDisk.getAbsolutePath().toCharArray()),
+ null /* no access restriction */);
+ this.inflatedClassFilesCache.put(name,ret);
+ return ret;
+ } catch (ClassFormatException e) {
+ return null; //!!! seems to match FileSystem behavior
+ } catch (IOException ex) {
+ return null; // see above...
+ }
}
}