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
32 public class WeakCache implements Cache {
33 private final Deque<Object> hardLinksToAvoidGarbageCollection;
34 private final ReferenceQueue<Object> queueOfGarbageCollectedEntries;
35 private final Cache delegate;
36 private int numberOfHardLinks;
37
38 public WeakCache(Cache delegate) {
39 this.delegate = delegate;
40 this.numberOfHardLinks = 256;
41 this.hardLinksToAvoidGarbageCollection = new LinkedList<>();
42 this.queueOfGarbageCollectedEntries = new ReferenceQueue<>();
43 }
44
45 @Override
46 public String getId() {
47 return delegate.getId();
48 }
49
50 @Override
51 public int getSize() {
52 removeGarbageCollectedItems();
53 return delegate.getSize();
54 }
55
56 public void setSize(int size) {
57 this.numberOfHardLinks = size;
58 }
59
60 @Override
61 public void putObject(Object key, Object value) {
62 removeGarbageCollectedItems();
63 delegate.putObject(key, new WeakEntry(key, value, queueOfGarbageCollectedEntries));
64 }
65
66 @Override
67 public Object getObject(Object key) {
68 Object result = null;
69 @SuppressWarnings("unchecked")
70 WeakReference<Object> weakReference = (WeakReference<Object>) delegate.getObject(key);
71 if (weakReference != null) {
72 result = weakReference.get();
73 if (result == null) {
74 delegate.removeObject(key);
75 } else {
76 synchronized (hardLinksToAvoidGarbageCollection) {
77 hardLinksToAvoidGarbageCollection.addFirst(result);
78 if (hardLinksToAvoidGarbageCollection.size() > numberOfHardLinks) {
79 hardLinksToAvoidGarbageCollection.removeLast();
80 }
81 }
82 }
83 }
84 return result;
85 }
86
87 @Override
88 public Object removeObject(Object key) {
89 removeGarbageCollectedItems();
90 @SuppressWarnings("unchecked")
91 WeakReference<Object> weakReference = (WeakReference<Object>) delegate.removeObject(key);
92 return weakReference == null ? null : weakReference.get();
93 }
94
95 @Override
96 public void clear() {
97 synchronized (hardLinksToAvoidGarbageCollection) {
98 hardLinksToAvoidGarbageCollection.clear();
99 }
100 removeGarbageCollectedItems();
101 delegate.clear();
102 }
103
104 private void removeGarbageCollectedItems() {
105 WeakEntry sv;
106 while ((sv = (WeakEntry) queueOfGarbageCollectedEntries.poll()) != null) {
107 delegate.removeObject(sv.key);
108 }
109 }
110
111 private static class WeakEntry extends WeakReference<Object> {
112 private final Object key;
113
114 private WeakEntry(Object key, Object value, ReferenceQueue<Object> garbageCollectionQueue) {
115 super(value, garbageCollectionQueue);
116 this.key = key;
117 }
118 }
119
120 }