Added AccessClassLoader test case

Test the release of WeakReferences to avoid ofending PermGen liberation on GC
This commit is contained in:
Tumi 2013-12-23 02:17:23 +01:00
parent 904c1dcc84
commit c63db34fa7

View File

@ -4,13 +4,119 @@ package com.esotericsoftware.reflectasm;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
import junit.framework.TestCase;
public class ClassLoaderTest extends TestCase {
public void testDifferentClassloaders () throws Exception {
// This classloader can see only the Test class and core Java classes.
ClassLoader testClassLoader = new ClassLoader() {
ClassLoader testClassLoader = new TestClassLoader1();
Class testClass = testClassLoader.loadClass("com.esotericsoftware.reflectasm.ClassLoaderTest$Test");
Object testObject = testClass.newInstance();
// Ensure AccessClassLoader can access both the Test class and FieldAccess.
FieldAccess access = FieldAccess.get(testObject.getClass());
access.set(testObject, "name", "first");
assertEquals("first", testObject.toString());
assertEquals("first", access.get(testObject, "name"));
}
public void testAutoUnloadClassloaders () throws Exception {
int initialCount = AccessClassLoader.activeAccessClassLoaders();
ClassLoader testClassLoader1 = new TestClassLoader1();
Class testClass1 = testClassLoader1.loadClass("com.esotericsoftware.reflectasm.ClassLoaderTest$Test");
Object testObject1 = testClass1.newInstance();
FieldAccess access1 = FieldAccess.get(testObject1.getClass());
access1.set(testObject1, "name", "first");
assertEquals("first", testObject1.toString());
assertEquals("first", access1.get(testObject1, "name"));
ClassLoader testClassLoader2 = new TestClassLoader2();
Class testClass2 = testClassLoader2.loadClass("com.esotericsoftware.reflectasm.ClassLoaderTest$Test");
Object testObject2 = testClass2.newInstance();
FieldAccess access2 = FieldAccess.get(testObject2.getClass());
access2.set(testObject2, "name", "second");
assertEquals("second", testObject2.toString());
assertEquals("second", access2.get(testObject2, "name"));
assertEquals(access1.getClass().toString(), access2.getClass().toString()); // Same class names
assertFalse(access1.getClass().equals(access2.getClass())); // But different classes
assertEquals(initialCount+2, AccessClassLoader.activeAccessClassLoaders());
testClassLoader1 = null;
testClass1 = null;
testObject1 = null;
access1 = null;
testClassLoader2 = null;
testClass2 = null;
testObject2 = null;
access2 = null;
// Force GC to reclaim unreachable (or only weak-reachable) objects
System.gc();
try {
Object[] array = new Object[(int) Runtime.getRuntime().maxMemory()];
System.out.println(array.length);
} catch (Throwable e) {
// Ignore OME
}
System.gc();
int times = 0;
while (AccessClassLoader.activeAccessClassLoaders()>1 && times < 50) { // max 5 seconds, should be instant
Thread.sleep(100); // test again
times++;
}
// Yeah, both reclaimed!
assertEquals(initialCount, AccessClassLoader.activeAccessClassLoaders());
}
public void testRemoveClassloaders () throws Exception {
int initialCount = AccessClassLoader.activeAccessClassLoaders();
ClassLoader testClassLoader1 = new TestClassLoader1();
Class testClass1 = testClassLoader1.loadClass("com.esotericsoftware.reflectasm.ClassLoaderTest$Test");
Object testObject1 = testClass1.newInstance();
FieldAccess access1 = FieldAccess.get(testObject1.getClass());
access1.set(testObject1, "name", "first");
assertEquals("first", testObject1.toString());
assertEquals("first", access1.get(testObject1, "name"));
ClassLoader testClassLoader2 = new TestClassLoader2();
Class testClass2 = testClassLoader2.loadClass("com.esotericsoftware.reflectasm.ClassLoaderTest$Test");
Object testObject2 = testClass2.newInstance();
FieldAccess access2 = FieldAccess.get(testObject2.getClass());
access2.set(testObject2, "name", "second");
assertEquals("second", testObject2.toString());
assertEquals("second", access2.get(testObject2, "name"));
assertEquals(access1.getClass().toString(), access2.getClass().toString()); // Same class names
assertFalse(access1.getClass().equals(access2.getClass())); // But different classes
assertEquals(initialCount+2, AccessClassLoader.activeAccessClassLoaders());
AccessClassLoader.remove(testObject1.getClass().getClassLoader());
assertEquals(initialCount+1, AccessClassLoader.activeAccessClassLoaders());
AccessClassLoader.remove(testObject2.getClass().getClassLoader());
assertEquals(initialCount+0, AccessClassLoader.activeAccessClassLoaders());
AccessClassLoader.remove(this.getClass().getClassLoader());
assertEquals(initialCount-1, AccessClassLoader.activeAccessClassLoaders());
}
static public class Test {
public String name;
public String toString () {
return name;
}
}
static public class TestClassLoader1 extends ClassLoader {
protected synchronized Class<?> loadClass (String name, boolean resolve) throws ClassNotFoundException {
Class c = findLoadedClass(name);
if (c != null) return c;
@ -39,22 +145,8 @@ public class ClassLoaderTest extends TestCase {
byte[] buffer = output.toByteArray();
return defineClass(name, buffer, 0, buffer.length);
}
};
Class testClass = testClassLoader.loadClass("com.esotericsoftware.reflectasm.ClassLoaderTest$Test");
Object testObject = testClass.newInstance();
// Ensure AccessClassLoader can access both the Test class and FieldAccess.
FieldAccess access = FieldAccess.get(testObject.getClass());
access.set(testObject, "name", "first");
assertEquals("first", testObject.toString());
assertEquals("first", access.get(testObject, "name"));
}
static public class Test {
public String name;
public String toString () {
return name;
}
static public class TestClassLoader2 extends TestClassLoader1 {
}
}