001
014
015 package com.liferay.portal.kernel.memory;
016
017 import com.liferay.portal.kernel.concurrent.ConcurrentIdentityHashMap;
018
019 import java.lang.ref.Reference;
020 import java.lang.ref.ReferenceQueue;
021
022 import java.util.Map;
023
024
027 public class FinalizeManager {
028
029 public static final ReferenceFactory PHANTOM_REFERENCE_FACTORY =
030 new ReferenceFactory() {
031
032 @Override
033 public <T> Reference<T> createReference(
034 T reference, ReferenceQueue<? super T> referenceQueue) {
035
036 return new EqualityPhantomReference<T>(
037 reference, referenceQueue) {
038
039 @Override
040 public void clear() {
041 _finalizeActions.remove(this);
042
043 super.clear();
044 }
045
046 };
047 }
048
049 };
050
051 public static final ReferenceFactory SOFT_REFERENCE_FACTORY =
052 new ReferenceFactory() {
053
054 @Override
055 public <T> Reference<T> createReference(
056 T reference, ReferenceQueue<? super T> referenceQueue) {
057
058 return new EqualitySoftReference<T>(reference, referenceQueue) {
059
060 @Override
061 public void clear() {
062 _finalizeActions.remove(this);
063
064 super.clear();
065 }
066
067 };
068 }
069
070 };
071
072 public static final boolean THREAD_ENABLED = Boolean.getBoolean(
073 FinalizeManager.class.getName() + ".thread.enabled");
074
075 public static final ReferenceFactory WEAK_REFERENCE_FACTORY =
076 new ReferenceFactory() {
077
078 @Override
079 public <T> Reference<T> createReference(
080 T reference, ReferenceQueue<? super T> referenceQueue) {
081
082 return new EqualityWeakReference<T>(reference, referenceQueue) {
083
084 @Override
085 public void clear() {
086 _finalizeActions.remove(this);
087
088 super.clear();
089 }
090
091 };
092 }
093
094 };
095
096 static {
097 if (THREAD_ENABLED) {
098 Thread thread = new FinalizeThread("Finalize Thread");
099
100 thread.setContextClassLoader(
101 FinalizeManager.class.getClassLoader());
102
103 thread.setDaemon(true);
104
105 thread.start();
106 }
107 }
108
109 public static <T> Reference<T> register(
110 T reference, FinalizeAction finalizeAction,
111 ReferenceFactory referenceFactory) {
112
113 Reference<T> newReference = referenceFactory.createReference(
114 reference, _referenceQueue);
115
116 _finalizeActions.put(newReference, finalizeAction);
117
118 if (!THREAD_ENABLED) {
119 _pollingCleanup();
120 }
121
122 return newReference;
123 }
124
125 public interface ReferenceFactory {
126
127 public <T> Reference<T> createReference(
128 T realReference, ReferenceQueue<? super T> referenceQueue);
129
130 }
131
132 private static void _finalizeReference(
133 Reference<? extends Object> reference) {
134
135 FinalizeAction finalizeAction = _finalizeActions.remove(reference);
136
137 if (finalizeAction != null) {
138 try {
139 finalizeAction.doFinalize(reference);
140 }
141 finally {
142 reference.clear();
143 }
144 }
145 }
146
147 private static void _pollingCleanup() {
148 Reference<? extends Object> reference = null;
149
150 while ((reference = _referenceQueue.poll()) != null) {
151 _finalizeReference(reference);
152 }
153 }
154
155 private static final Map<Reference<?>, FinalizeAction> _finalizeActions =
156 new ConcurrentIdentityHashMap<>();
157 private static final ReferenceQueue<Object> _referenceQueue =
158 new ReferenceQueue<>();
159
160 private static class FinalizeThread extends Thread {
161
162 public FinalizeThread(String name) {
163 super(name);
164 }
165
166 @Override
167 public void run() {
168 while (true) {
169 try {
170 _finalizeReference(_referenceQueue.remove());
171 }
172 catch (InterruptedException ie) {
173 }
174 }
175 }
176
177 }
178
179 }