1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.ibatis.cache.decorators;
17
18 import java.lang.ref.ReferenceQueue;
19 import java.lang.ref.WeakReference;
20 import java.util.Deque;
21 import java.util.LinkedList;
22
23 import org.apache.ibatis.cache.Cache;
24
25
26
27
28
29
30
31 public class WeakCache implements Cache {
32 private final Deque<Object> hardLinksToAvoidGarbageCollection;
33 private final ReferenceQueue<Object> queueOfGarbageCollectedEntries;
34 private final Cache delegate;
35 private int numberOfHardLinks;
36
37 public WeakCache(Cache delegate) {
38 this.delegate = delegate;
39 this.numberOfHardLinks = 256;
40 this.hardLinksToAvoidGarbageCollection = new LinkedList<>();
41 this.queueOfGarbageCollectedEntries = new ReferenceQueue<>();
42 }
43
44 @Override
45 public String getId() {
46 return delegate.getId();
47 }
48
49 @Override
50 public int getSize() {
51 removeGarbageCollectedItems();
52 return delegate.getSize();
53 }
54
55 public void setSize(int size) {
56 this.numberOfHardLinks = size;
57 }
58
59 @Override
60 public void putObject(Object key, Object value) {
61 removeGarbageCollectedItems();
62 delegate.putObject(key, new WeakEntry(key, value, queueOfGarbageCollectedEntries));
63 }
64
65 @Override
66 public Object getObject(Object key) {
67 Object result = null;
68 @SuppressWarnings("unchecked")
69 WeakReference<Object> weakReference = (WeakReference<Object>) delegate.getObject(key);
70 if (weakReference != null) {
71 result = weakReference.get();
72 if (result == null) {
73 delegate.removeObject(key);
74 } else {
75 hardLinksToAvoidGarbageCollection.addFirst(result);
76 if (hardLinksToAvoidGarbageCollection.size() > numberOfHardLinks) {
77 hardLinksToAvoidGarbageCollection.removeLast();
78 }
79 }
80 }
81 return result;
82 }
83
84 @Override
85 public Object removeObject(Object key) {
86 removeGarbageCollectedItems();
87 return delegate.removeObject(key);
88 }
89
90 @Override
91 public void clear() {
92 hardLinksToAvoidGarbageCollection.clear();
93 removeGarbageCollectedItems();
94 delegate.clear();
95 }
96
97 private void removeGarbageCollectedItems() {
98 WeakEntry sv;
99 while ((sv = (WeakEntry) queueOfGarbageCollectedEntries.poll()) != null) {
100 delegate.removeObject(sv.key);
101 }
102 }
103
104 private static class WeakEntry extends WeakReference<Object> {
105 private final Object key;
106
107 private WeakEntry(Object key, Object value, ReferenceQueue<Object> garbageCollectionQueue) {
108 super(value, garbageCollectionQueue);
109 this.key = key;
110 }
111 }
112
113 }