ClassLoaderRepositoryTest.java
/* *******************************************************************
* Copyright (c) 2006 Contributors
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Eclipse Public License v 2.0
* which accompanies this distribution and is available at
* https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
*
* Contributors:
* Andy Clement initial implementation
* ******************************************************************/
package org.aspectj.weaver.bcel;
import java.io.File;
import java.lang.ref.Reference;
import java.lang.reflect.Field;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Enumeration;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import org.aspectj.apache.bcel.util.ClassLoaderRepository;
import junit.framework.TestCase;
/** NOT YET INCLUDED IN A FULL TEST RUN - WORK IN PROGRESS CHECKING CLASSLOADERREPOSITORY OPTIMIZATIONS */
public class ClassLoaderRepositoryTest extends TestCase {
private File f;
private ZipFile zf;
private Enumeration entries;
private Map map;
public void setUp() throws Exception {
f = new File("../lib/aspectj/lib/aspectjtools.jar");
assertTrue("Couldn't find aspectjtools to test. Tried: "+f.getAbsolutePath(),f.exists());
zf = new ZipFile(f);
entries = zf.entries();
// ClassLoaderRepository.sharedCacheCompactFrequency = 16384;
map = getSharedMap();
}
public void tearDown() {
new ClassLoaderRepository((ClassLoader) null).reset();
}
private ClassLoaderRepository setupRepository() throws Exception {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
ClassLoader res = new URLClassLoader(new URL[]{f.toURI().toURL()},cl);
ClassLoaderRepository rep = new ClassLoaderRepository(res);
return rep;
}
private void compareTwoRepositories() throws Exception {
ClassLoaderRepository rep1 = setupRepository();
ClassLoaderRepository rep2 = setupRepository();
int i = 0;
while (entries.hasMoreElements()) {
ZipEntry zfe = (ZipEntry)entries.nextElement();
String classfileName = zfe.getName();
if (classfileName.endsWith(".class")) {
String clazzname = classfileName.substring(0,classfileName.length()-6).replace('/','.');
// twice by each
rep1.loadClass(clazzname);
rep1.loadClass(clazzname);
rep2.loadClass(clazzname);
rep2.loadClass(clazzname);
i++;
}
}
System.err.println("Successfully compared "+i+" entries!!");
System.err.println(rep1.report());
System.err.println(rep2.report());
}
// private void loadOnce() throws Exception {
// ClassLoaderRepository rep = setupRepository();
// while (entries.hasMoreElements()) {
// ZipEntry zfe = (ZipEntry) entries.nextElement();
// String classfileName = zfe.getName();
// if (classfileName.endsWith(".class")) {
// String clazzname = classfileName.substring(0,
// classfileName.length() - 6).replace('/', '.');
//
// rep.loadClass(clazzname);
// }
// }
// }
public void testMultiThreaded() throws Throwable {
ClassLoaderRepository.useSharedCache=true;
// ClassLoaderRepository.sharedCacheCompactFrequency = 200;
//loadOnce();
TestThread threads[] = new TestThread[6];
for (int i=0; i<threads.length; i++) {
threads[i] = new TestThread((i%3)*1000);
threads[i].start();
}
for (TestThread thread : threads) {
thread.join();
if (thread.getFailure() != null) {
throw thread.getFailure();
}
}
}
private class TestThread extends Thread {
public Throwable failure = null;
Enumeration entries;
// ensure the threads are loading DIFFERENT shared classes at the same time...
public TestThread(int skip) {
entries = zf.entries();
for (int i=0; i<skip && entries.hasMoreElements(); i++) {
entries.nextElement();
}
}
public void run() {
try {
ClassLoaderRepository rep = setupRepository();
int i = 0;
while (entries.hasMoreElements()) {
ZipEntry zfe = (ZipEntry)entries.nextElement();
String classfileName = zfe.getName();
if (classfileName.endsWith(".class")) {
String clazzname = classfileName.substring(0,classfileName.length()-6).replace('/','.');
rep.loadClass(clazzname);
rep.loadClass(clazzname);
i++;
}
}
System.err.println("Thread finished: "+rep.report());
} catch (Throwable t) {
failure = t;
}
}
public Throwable getFailure() {
return failure;
}
}
public void testNotSharedRepository() throws Exception {
ClassLoaderRepository.useSharedCache=false;
compareTwoRepositories();
}
public void testSharedUrlRepository() throws Exception {
ClassLoaderRepository.useSharedCache=true;
compareTwoRepositories();
// ClassLoaderRepository.compactSharedCache();
}
public void testPurgeUrlRepository() throws Exception {
ClassLoaderRepository.useSharedCache = true;
ClassLoaderRepository rep = setupRepository();
Reference ref = null;
while (ref==null && entries.hasMoreElements()) {
ZipEntry zfe = (ZipEntry)entries.nextElement();
String classfileName = zfe.getName();
if (classfileName.endsWith(".class")) {
String clazzname = classfileName.substring(0,classfileName.length()-6).replace('/','.');
rep.loadClass(clazzname);
assertEquals("expected one entry in shared URL cache "+map.size()+": "+map, 1, map.size());
ref = (Reference)map.values().iterator().next();
ref.clear();
ref.enqueue();
map.size();//force purge
}
}
assertEquals("expected empty shared URL cache "+map.size(), 0, map.size());
}
public void testAutoPurgeUrlRepository() throws Exception {
ClassLoaderRepository.useSharedCache = true;
assertEquals("expected empty shared URL cache "+map.size(), 0, map.size());
ClassLoaderRepository rep = setupRepository();
Reference ref = null;
int i = 0;
while (i<3 && entries.hasMoreElements()) {
ZipEntry zfe = (ZipEntry)entries.nextElement();
String classfileName = zfe.getName();
if (classfileName.endsWith(".class")) {
String clazzname = classfileName.substring(0,classfileName.length()-6).replace('/','.');
rep.loadClass(clazzname);
ref = (Reference)map.values().iterator().next();
ref.clear();
ref.enqueue();
i++;
}
}
assertTrue("expected smaller shared URL cache "+map.size(), map.size()<3);
}
private Field getSharedMapField() throws Exception {
Field field = ClassLoaderRepository.class.getDeclaredField("sharedCache");
field.setAccessible(true);
return field;
}
private Map getSharedMap() throws Exception {
return (Map)getSharedMapField() .get(null);
}
}