Browse Source

Some more fixes for Bug 78954: Compiler cannot cope with 4000 jars on the classpath.

- ClassPathManager can now manage its set of open archives, rather than being 'unlimited' it now limits itself to 1000 open archives (which can be increased via a sys prop).
- BcelWorld is changed to add a tidy up method that can tell class path manager to close its archives (useful for the IDE)
- BcelWorld is also changed to ensure 'it' is the repository used to resolve classes, there were previously some situations where BCEL would start loading classes itself (creating duplicates in memory of things like java/lang/String etc).  I'm not sure if this will alter our performance/memory characteristics.
tags/Root_AspectJ5_Development
aclement 19 years ago
parent
commit
837c97b0dd

+ 12
- 1
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/EclipseClassPathManager.java View File

@@ -97,6 +97,7 @@ public class EclipseClassPathManager extends ClassPathManager {
private class ClassFileReaderBackedClassFile extends ClassPathManager.ClassFile {

private ClassFileReader source;
private InputStream is;
public ClassFileReaderBackedClassFile(ClassFileReader cfr) {
source = cfr;
@@ -106,8 +107,18 @@ public class EclipseClassPathManager extends ClassPathManager {
* @see org.aspectj.weaver.bcel.ClassPathManager.ClassFile#getInputStream()
*/
public InputStream getInputStream() throws IOException {
return new ByteArrayInputStream(source.getReferenceBytes());
is = new ByteArrayInputStream(source.getReferenceBytes());
return is;
}
public void close() {
try {
if (is!=null) is.close();
} catch (IOException e) {
// Should never happen !
e.printStackTrace();
}
}

/* (non-Javadoc)
* @see org.aspectj.weaver.bcel.ClassPathManager.ClassFile#getPath()

+ 39
- 2
weaver/src/org/aspectj/weaver/bcel/BcelWorld.java View File

@@ -33,6 +33,7 @@ import org.aspectj.apache.bcel.generic.InvokeInstruction;
import org.aspectj.apache.bcel.generic.PUTSTATIC;
import org.aspectj.apache.bcel.generic.Type;
import org.aspectj.apache.bcel.util.ClassPath;
import org.aspectj.apache.bcel.util.Repository;
import org.aspectj.bridge.IMessageHandler;
import org.aspectj.weaver.Advice;
import org.aspectj.weaver.AdviceKind;
@@ -49,7 +50,7 @@ import org.aspectj.weaver.patterns.FormalBinding;
import org.aspectj.weaver.patterns.Pointcut;
import org.aspectj.weaver.patterns.SimpleScope;

public class BcelWorld extends World {
public class BcelWorld extends World implements Repository {
private ClassPathManager classPath;
//private ClassPathManager aspectPath = null;
@@ -88,12 +89,16 @@ public class BcelWorld extends World {
this.classPath = new ClassPathManager(classPath, handler);
setMessageHandler(handler);
setXRefHandler(xrefHandler);
// Tell BCEL to use us for resolving any classes
org.aspectj.apache.bcel.Repository.setRepository(this);
}
public BcelWorld(ClassPathManager cpm, IMessageHandler handler, ICrossReferenceHandler xrefHandler) {
this.classPath = cpm;
setMessageHandler(handler);
setXRefHandler(xrefHandler);
// Tell BCEL to use us for resolving any classes
org.aspectj.apache.bcel.Repository.setRepository(this);
}
public void addPath (String name) {
@@ -220,7 +225,7 @@ public class BcelWorld extends World {
ClassParser parser = new ClassParser(file.getInputStream(), file.getPath());
JavaClass jc = parser.parse();
file.close();
return jc;
} catch (IOException ioe) {
return null;
@@ -367,4 +372,36 @@ public class BcelWorld extends World {
return (BcelObjectType) ((ResolvedTypeX.Name)concreteAspect).getDelegate();
}

public void tidyUp() {
// At end of compile, close any open files so deletion of those archives is possible
classPath.closeArchives();
}

/// The repository interface methods

public JavaClass findClass(String className) {
return lookupJavaClass(classPath,className);
}

public JavaClass loadClass(String className) throws ClassNotFoundException {
return lookupJavaClass(classPath,className);
}

public void storeClass(JavaClass clazz) {
throw new RuntimeException("Not implemented");
}

public void removeClass(JavaClass clazz) {
throw new RuntimeException("Not implemented");
}

public JavaClass loadClass(Class clazz) throws ClassNotFoundException {
throw new RuntimeException("Not implemented");
}

public void clear() {
throw new RuntimeException("Not implemented");
}

}

+ 118
- 14
weaver/src/org/aspectj/weaver/bcel/ClassPathManager.java View File

@@ -26,6 +26,7 @@ import java.util.zip.ZipFile;

import org.aspectj.bridge.IMessageHandler;
import org.aspectj.bridge.MessageUtil;
import org.aspectj.weaver.BCException;
import org.aspectj.weaver.TypeX;
import org.aspectj.weaver.WeaverMessages;

@@ -34,6 +35,22 @@ public class ClassPathManager {
private List entries;
// In order to control how many open files we have, we maintain a list.
// The max number is configured through the property:
// org.aspectj.weaver.openarchives
// and it defaults to 1000
private List openArchives = new ArrayList();
private static int maxOpenArchives = -1;
private static final int MAXOPEN_DEFAULT = 1000;
static {
String openzipsString = getSystemPropertyWithoutSecurityException("org.aspectj.weaver.openzips",Integer.toString(MAXOPEN_DEFAULT));
maxOpenArchives=Integer.parseInt(openzipsString);
if (maxOpenArchives<20) maxOpenArchives=1000;
}
public ClassPathManager(List classpath, IMessageHandler handler) {
entries = new ArrayList();
for (Iterator i = classpath.iterator(); i.hasNext();) {
@@ -106,25 +123,37 @@ public class ClassPathManager {
public abstract static class ClassFile {
public abstract InputStream getInputStream() throws IOException;
public abstract String getPath();
public abstract void close();
}


public abstract static class Entry {
public abstract ClassFile find(String name);
public abstract List getAllClassFiles();
}
private static class FileClassFile extends ClassFile {
private File file;
private FileInputStream fis;
public FileClassFile(File file) {
this.file = file;
}
public InputStream getInputStream() throws IOException {
return new FileInputStream(file);
fis = new FileInputStream(file);
return fis;
}
public void close() {
try {
if (fis!=null) fis.close();
} catch (IOException ioe) {
throw new BCException("Can't close class file : "+file.getName()+": "+ioe.toString());
} finally {
fis = null;
}
}
public String getPath() { return file.getPath(); }
}
@@ -147,58 +176,133 @@ public class ClassPathManager {
public String toString() { return dirPath; }
}
private static class ZipEntryClassFile extends ClassFile {
private ZipEntry entry;
private ZipFile zipFile;
public ZipEntryClassFile(ZipFile zipFile, ZipEntry entry) {
private ZipFileEntry zipFile;
private InputStream is;
public ZipEntryClassFile(ZipFileEntry zipFile, ZipEntry entry) {
this.zipFile = zipFile;
this.entry = entry;
}
public InputStream getInputStream() throws IOException {
return zipFile.getInputStream(entry);
is = zipFile.getZipFile().getInputStream(entry);
return is;
}
public void close() {
try {
if (is!=null) is.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
is = null;
}
}
public String getPath() { return entry.getName(); }
}
public class ZipFileEntry extends Entry {
private File file;
private ZipFile zipFile;
public ZipFileEntry(File file) throws IOException {
this(new ZipFile(file));
this.file = file;
}
public ZipFileEntry(ZipFile zipFile) {
this.zipFile = zipFile;
}
public ZipFile getZipFile() {
return zipFile;
}
public ClassFile find(String name) {
ensureOpen();
String key = name.replace('.', '/') + ".class";
ZipEntry entry = zipFile.getEntry(key);
if (entry != null) return new ZipEntryClassFile(zipFile, entry);
else return null;
if (entry != null) return new ZipEntryClassFile(this, entry);
else return null; // This zip will be closed when necessary...
}
public List getAllClassFiles() {
ensureOpen();
List ret = new ArrayList();
for (Enumeration e = zipFile.entries(); e.hasMoreElements(); ) {
ZipEntry entry = (ZipEntry)e.nextElement();
String name = entry.getName();
if (hasClassExtension(name)) ret.add(new ZipEntryClassFile(zipFile, entry));
if (hasClassExtension(name)) ret.add(new ZipEntryClassFile(this, entry));
}
// if (ret.isEmpty()) close();
return ret;
}

public String toString() { return zipFile.getName(); }
private void ensureOpen() {
if (zipFile != null) return; // If its not null, the zip is already open
try {
if (openArchives.size()>=maxOpenArchives) {
closeSomeArchives(openArchives.size()/10); // Close 10% of those open
}
zipFile = new ZipFile(file);
openArchives.add(zipFile);
} catch (IOException ioe) {
throw new BCException("Can't open archive: "+file.getName()+": "+ioe.toString());
}
}
public void closeSomeArchives(int n) {
for (int i=n-1;i>=0;i--) {
ZipFile zf = (ZipFile)openArchives.get(i);
try {
zf.close();
} catch (IOException e) {
e.printStackTrace();
}
openArchives.remove(i);
}
}
public void close() {
if (zipFile == null) return;
try {
openArchives.remove(zipFile);
zipFile.close();
} catch (IOException ioe) {
throw new BCException("Can't close archive: "+file.getName()+": "+ioe.toString());
} finally {
zipFile = null;
}
}
public String toString() { return file.getName(); }
}


/* private */ static boolean hasClassExtension(String name) {
return name.toLowerCase().endsWith((".class"));
}

public void closeArchives() {
for (Iterator i = entries.iterator(); i.hasNext(); ) {
Entry entry = (Entry)i.next();
if (entry instanceof ZipFileEntry) {
((ZipFileEntry)entry).close();
}
openArchives.clear();
}
}
// Copes with the security manager
private static String getSystemPropertyWithoutSecurityException (String aPropertyName, String aDefaultValue) {
try {
return System.getProperty(aPropertyName, aDefaultValue);
} catch (SecurityException ex) {
return aDefaultValue;
}
}
}

Loading…
Cancel
Save