JRE Memory Leak Prevention Listener (org.apache.catalina.core.JreMemoryLeakPreventionListener)
gcDaemonProtection |
Enables protection so that calls to |
public static LatencyRequest requestLatency(long latency)
-
Makes a new request for a garbage-collection latency of the given number of real-time milliseconds. A low-priority daemon thread makes a best effort to ensure that the maximum object-inspection age never exceeds the smallest of the currently active requests.
270 public static LatencyRequest requestLatency(long latency) {
271 return new LatencyRequest(latency);
272 }
167 /**
168 * Represents an active garbage-collection latency request.
Instances of
169 * this class are created by the <code>{@link #requestLatency}</code>
170 * method. Given a request, the only interesting operation is that of
171 * cancellation. 172 */
173 public static class LatencyRequest implements Comparable {
174
175 /* Instance counter, used to generate unique identifers */
176 private static long counter = 0;
177
178 /* Sorted set of active latency requests */
179 private static SortedSet requests = null;
180
181 /* Examine the request set and reset the latency target if necessary.
182 * Must be invoked while holding the lock.
183 */
184 private static void adjustLatencyIfNeeded() {
185 if ((requests == null) || requests.isEmpty()) {
186 if (latencyTarget != NO_TARGET) {
187 setLatencyTarget(NO_TARGET);
188 }
189 } else {
190 LatencyRequest r = (LatencyRequest)requests.first();
191 if (r.latency != latencyTarget) {
192 setLatencyTarget(r.latency);
193 }
194 }
195 }
196
197 /* The requested latency, or NO_TARGET
198 * if this request has been cancelled
199 */
200 private long latency;
201
202 /* Unique identifier for this request */
203 private long id;
204
205 private LatencyRequest(long ms) {
206 if (ms <= 0) {
207 throw new IllegalArgumentException("Non-positive latency: "
208 + ms);
209 }
210 this.latency = ms;
211 synchronized (lock) {
212 this.id = ++counter;
213 if (requests == null) {
214 requests = new TreeSet();
215 }
216 requests.add(this);
217 adjustLatencyIfNeeded();
218 }
219 }
220
221 /**
222 * Cancels this latency request.
223 *
224 * @throws IllegalStateException
225 * If this request has already been cancelled
226 */
227 public void cancel() {
228 synchronized (lock) {
229 if (this.latency == NO_TARGET) {
230 throw new IllegalStateException("Request already"
231 + " cancelled");
232 }
233 if (!requests.remove(this)) {
234 throw new InternalError("Latency request "
235 + this + " not found");
236 }
237 if (requests.isEmpty()) requests = null;
238 this.latency = NO_TARGET;
239 adjustLatencyIfNeeded();
240 }
241 }
242
243 public int compareTo(Object o) {
244 LatencyRequest r = (LatencyRequest)o;
245 long d = this.latency - r.latency;
246 if (d == 0) d = this.id - r.id;
247 return (d < 0) ? -1 : ((d > 0) ? +1 : 0);
248 }
249
250 public String toString() {
251 return (LatencyRequest.class.getName()
252 + "[" + latency + "," + id + "]");
253 }
254
255 }
256
150 /* Sets the latency target to the given value. 151 * Must be invoked while holding the lock. 152 */ 153 private static void setLatencyTarget(long ms) { 154 latencyTarget = ms; 155 if (daemon == null) { 156 /* Create a new daemon thread */ 157 Daemon.create(); 158 } else { 159 /* Notify the existing daemon thread 160 * that the lateency target has changed 161 */ 162 lock.notify(); 163 } 164 }
63 private static class LatencyLock extends Object { };64 private static Object lock = new LatencyLock();
private static class Daemon extends Thread {
87
88 public void run() {
89 for (;;) {
90 long l;
91 synchronized (lock) {
92
93 l = latencyTarget;
94 if (l == NO_TARGET) {
95 /* No latency target, so exit */
96 GC.daemon = null;
97 return; 98 }
99
100 long d = maxObjectInspectionAge();
101 if (d >= l) {
102 /* Do a full collection. There is a remote possibility
103 * that a full collection will occurr between the time
104 * we sample the inspection age and the time the GC
105 * actually starts, but this is sufficiently unlikely
106 * that it doesn't seem worth the more expensive JVM
107 * interface that would be required.
108 */
109 System.gc();
110 d = 0;
111 }
112
113 /* Wait for the latency period to expire,
114 * or for notification that the period has changed
115 */
116 try {
117 lock.wait(l - d);
118 } catch (InterruptedException x) {
119 continue;
120 }
121 }
122 }
123 }
124
125 private Daemon(ThreadGroup tg) {
126 super(tg, "GC Daemon");
127 }
128
129 /* Create a new daemon thread in the root thread group */
130 public static void create() {
131 PrivilegedAction pa = new PrivilegedAction() {
132 public Object run() {
133 ThreadGroup tg = Thread.currentThread().getThreadGroup();
134 for (ThreadGroup tgn = tg;
135 tgn != null;
136 tg = tgn, tgn = tg.getParent());
137 Daemon d = new Daemon(tg);
138 d.setDaemon(true);
139 d.setPriority(Thread.MIN_PRIORITY + 1);
140 d.start();
141 GC.daemon = d;
142 return null;
143 }};
144 AccessController.doPrivileged(pa);
145 }
146
147 }
-
Returns the maximum object-inspection age, which is the number
of real-time milliseconds that have elapsed since the
least-recently-inspected heap object was last inspected by the garbage
collector.
public static long currentLatencyTarget()
-
Returns the current smallest garbage-collection latency request, or zero if there are no active requests.
-
public static native long maxObjectInspectionAge()
-
Returns the maximum object-inspection age, which is the number
of real-time milliseconds that have elapsed since the
least-recently-inspected heap object was last inspected by the garbage
collector.
For simple stop-the-world collectors this value is just the time since the most recent collection. For generational collectors it is the time since the oldest generation was most recently collected. Other collectors are free to return a pessimistic estimate of the elapsed time, or simply the time since the last full collection was performed.
Note that in the presence of reference objects, a given object that is no longer strongly reachable may have to be inspected multiple times before it can be reclaimed.
'java core' 카테고리의 다른 글
로그를 통해서 ClassLoading 순서 보기 (0) | 2010.06.03 |
---|---|
Class.getResource()와 Class.getClassLoader().getResource() 의 차이점 (0) | 2010.05.28 |
System.arraycopy보다 유연한 Arrays.copyOf 메서드 (0) | 2010.05.13 |
String의 intern 메소드에 대해서 잘 쓴 글 (0) | 2010.05.13 |
Tomcat6.0.26과 jdk7,jdk6을 사용하지 말 것 (0) | 2010.05.13 |