Skip to content

Instantly share code, notes, and snippets.

@dragonsinth
Created October 29, 2015 21:46
Show Gist options
  • Save dragonsinth/4d5ed3a96fc411d4dc48 to your computer and use it in GitHub Desktop.
Save dragonsinth/4d5ed3a96fc411d4dc48 to your computer and use it in GitHub Desktop.
Demonstration of weak mapping class objects
package test;
import com.google.common.collect.MapMaker;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.concurrent.ConcurrentMap;
import static org.junit.Assert.*;
public class PinningTest {
public static void main(String[] args) throws Exception {
ConcurrentMap<Class, Method> toStringMethodMap = buildClassMap();
assertTrue(toStringMethodMap.entrySet().iterator().hasNext());
int i = 0;
while (i < 100 && toStringMethodMap.entrySet().iterator().hasNext()) {
System.gc();
++i;
}
System.out.println(i);
}
private static ConcurrentMap<Class, Method> buildClassMap() throws Exception {
Class<?> clazz = getIsolatedClass();
ConcurrentMap<Class, Method> toStringMethodMap = new MapMaker().weakKeys().weakValues().makeMap();
toStringMethodMap.put(clazz, clazz.getMethod("toString"));
assertNotNull(toStringMethodMap.get(clazz));
return toStringMethodMap;
}
private static Class<?> getIsolatedClass() throws Exception {
final byte[] testClassBytes = getTestClassBytes();
ClassLoader classLoader = new ClassLoader(getBootstrapClassLoader()) {
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
if (!name.equals(TestClass.class.getName())) {
return super.findClass(name);
}
return defineClass(name, testClassBytes, 0, testClassBytes.length);
}
};
Class<?> clazz = classLoader.loadClass(TestClass.class.getName());
checkClass(clazz);
return clazz;
}
private static void checkClass(Class<?> clazz) throws Exception {
assertNotSame(clazz, TestClass.class);
Constructor<?> ctor = clazz.getConstructor();
ctor.setAccessible(true);
Object testInstance = ctor.newInstance();
assertEquals("TestClass", testInstance.toString());
}
private static byte[] getTestClassBytes() {
try {
try (InputStream stream = PinningTest.class.getResourceAsStream("TestClass.class")) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
int count;
while((count = stream.read(buf)) >= 0) {
baos.write(buf, 0, count);
}
return baos.toByteArray();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
static ClassLoader getBootstrapClassLoader() {
ClassLoader result = ClassLoader.getSystemClassLoader();
while (result.getParent() != null) {
result = result.getParent();
}
return result;
}
}
class TestClass {
public TestClass() {
}
public String toString() {
return "TestClass";
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment