On 18.05.16 09:10, Jochen Theodorou wrote:
private static class GlobalClassSet {
//private final ManagedLinkedList<ClassInfo> items = new
ManagedLinkedList<ClassInfo>(weakBundle);
private final WeakHashMap<Class,WeakReference<ClassInfo>> items
= new WeakHashMap<Class,WeakReference<ClassInfo>>();
would be actually interesting to keep the list and see if it can still
garbage collect
Looks like it can. (As I would have expected because
ClassInfo.remove(clazz) did not touch that list before and that was
sufficient to get GC on-the-fly provided you also do
Introspector.flushFromCaches(clazz) ):
--
private static class GlobalClassSet {
private final ManagedLinkedList<ClassInfo> itemsList = new
ManagedLinkedList<ClassInfo>(weakBundle);
private final WeakHashMap<Class,WeakReference<ClassInfo>>
itemsMap = new WeakHashMap<Class,WeakReference<ClassInfo>>();
public int size(){
return values().size();
}
public int fullSize(){
return values().size();
}
public Collection<ClassInfo> values(){
synchronized(itemsList){
return Arrays.asList(itemsList.toArray(new ClassInfo[0]));
}
}
public void add(ClassInfo value){
synchronized(itemsList) {
itemsList.add(value);
}
synchronized(itemsMap) {
itemsMap.put(value.klazz, new
WeakReference<ClassInfo>(value));
}
}
public ClassInfo get(Class cls) {
WeakReference<ClassInfo> ref;
synchronized(itemsMap) {
ref = itemsMap.get(cls);
}
ClassInfo info;
if (ref == null) {
//System.out.println("ClassInfo Ref is null: " +
cls.getName());
info = new ClassInfo(cls);
synchronized (itemsMap) {
itemsMap.put(cls, new WeakReference<ClassInfo>(info));
}
return info;
}
info = ref.get();
if (info == null) {
//System.out.println("ClassInfo is null: " +
cls.getName());
info = new ClassInfo(cls);
itemsMap.put(cls, new WeakReference<ClassInfo>(info));
return info;
}
return info;
}
}
--
$ java -XX:MaxMetaspaceSize=64m -Xmx512m -cp .:groovy-2.5.0-SNAPSHOT.jar
ClassGCTester -cp filling/ -parent tester -classes GroovyFilling
(does a Introspector.flushFromCaches(clazz) for each loaded class)
Secs Test classes Metaspace/PermGen Heap Load time Create
time Run time Cleanup time
#loaded #remaining used committed used
committed average average average average
0 1 1 6.3m 6.5m 13.4m 245.5m
0.890ms 14.308ms 0.026168ms 0.019285ms
1 435 435 8.9m 10.1m 22.1m 245.5m
0.365ms 1.825ms 0.000064ms 0.000009ms
2 1202 1202 11.9m 14.6m 66.1m 245.5m
0.280ms 1.314ms 0.000024ms 0.000001ms
3 2197 2197 15.7m 20.4m 83.8m 309.5m
0.240ms 1.070ms 0.000010ms 0.000001ms
4 3247 966 11.0m 16.8m 16.5m 242.0m
0.226ms 0.959ms 0.000006ms 0.000000ms
5 4396 2115 15.4m 20.3m 44.5m 238.0m
0.208ms 0.886ms 0.000005ms 0.000000ms
6 5415 3134 19.3m 26.0m 54.4m 235.5m
0.202ms 0.863ms 0.000009ms 0.000000ms
7 6458 667 9.8m 18.0m 94.7m 266.5m
0.203ms 0.839ms 0.000003ms 0.000000ms
8 7550 1759 14.0m 21.4m 122.0m 268.5m
0.198ms 0.821ms 0.000003ms 0.000000ms
9 8748 2957 18.6m 25.9m 46.3m 268.5m
0.191ms 0.799ms 0.000003ms 0.000000ms
[...]
Very interesting because the list contains references to the class and
yet it can be garbage collected on-the-fly... Maybe that could help to
find a solution?
Alain