History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/misc/GC.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/misc/GC.java+284−0
@@ -0,0 +1,284 @@
1+/*
2+ * Copyright (c) 1998, 2008, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.misc;
27+
28+import java.security.AccessController;
29+import java.security.PrivilegedAction;
30+import java.util.SortedSet;
31+import java.util.TreeSet;
32+
33+
34+/**
35+ * Support for garbage-collection latency requests.
36+ *
37+ * @author Mark Reinhold
38+ * @since 1.2
39+ */
40+
41+public class GC {
42+
43+ private GC() { } /* To prevent instantiation */
44+
45+
46+ /* Latency-target value indicating that there's no active target
47+ */
48+ private static final long NO_TARGET = Long.MAX_VALUE;
49+
50+ /* The current latency target, or NO_TARGET if there is no target
51+ */
52+ private static long latencyTarget = NO_TARGET;
53+
54+ /* The daemon thread that implements the latency-target mechanism,
55+ * or null if there is presently no daemon thread
56+ */
57+ private static Thread daemon = null;
58+
59+ /* The lock object for the latencyTarget and daemon fields. The daemon
60+ * thread, if it exists, waits on this lock for notification that the
61+ * latency target has changed.
62+ */
63+ private static class LatencyLock extends Object { };
64+ private static Object lock = new LatencyLock();
65+
66+
67+ /**
68+ * Returns the maximum <em>object-inspection age</em>, which is the number
69+ * of real-time milliseconds that have elapsed since the
70+ * least-recently-inspected heap object was last inspected by the garbage
71+ * collector.
72+ *
73+ * <p> For simple stop-the-world collectors this value is just the time
74+ * since the most recent collection. For generational collectors it is the
75+ * time since the oldest generation was most recently collected. Other
76+ * collectors are free to return a pessimistic estimate of the elapsed
77+ * time, or simply the time since the last full collection was performed.
78+ *
79+ * <p> Note that in the presence of reference objects, a given object that
80+ * is no longer strongly reachable may have to be inspected multiple times
81+ * before it can be reclaimed.
82+ */
83+ public static native long maxObjectInspectionAge();
84+
85+
86+ 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<Void> pa = new PrivilegedAction<Void>() {
132+ public Void 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+ }
148+
149+
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+ }
165+
166+
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
174+ implements Comparable<LatencyRequest> {
175+
176+ /* Instance counter, used to generate unique identifers */
177+ private static long counter = 0;
178+
179+ /* Sorted set of active latency requests */
180+ private static SortedSet<LatencyRequest> requests = null;
181+
182+ /* Examine the request set and reset the latency target if necessary.
183+ * Must be invoked while holding the lock.
184+ */
185+ private static void adjustLatencyIfNeeded() {
186+ if ((requests == null) || requests.isEmpty()) {
187+ if (latencyTarget != NO_TARGET) {
188+ setLatencyTarget(NO_TARGET);
189+ }
190+ } else {
191+ LatencyRequest r = requests.first();
192+ if (r.latency != latencyTarget) {
193+ setLatencyTarget(r.latency);
194+ }
195+ }
196+ }
197+
198+ /* The requested latency, or NO_TARGET
199+ * if this request has been cancelled
200+ */
201+ private long latency;
202+
203+ /* Unique identifier for this request */
204+ private long id;
205+
206+ private LatencyRequest(long ms) {
207+ if (ms <= 0) {
208+ throw new IllegalArgumentException("Non-positive latency: "
209+ + ms);
210+ }
211+ this.latency = ms;
212+ synchronized (lock) {
213+ this.id = ++counter;
214+ if (requests == null) {
215+ requests = new TreeSet<LatencyRequest>();
216+ }
217+ requests.add(this);
218+ adjustLatencyIfNeeded();
219+ }
220+ }
221+
222+ /**
223+ * Cancels this latency request.
224+ *
225+ * @throws IllegalStateException
226+ * If this request has already been cancelled
227+ */
228+ public void cancel() {
229+ synchronized (lock) {
230+ if (this.latency == NO_TARGET) {
231+ throw new IllegalStateException("Request already"
232+ + " cancelled");
233+ }
234+ if (!requests.remove(this)) {
235+ throw new InternalError("Latency request "
236+ + this + " not found");
237+ }
238+ if (requests.isEmpty()) requests = null;
239+ this.latency = NO_TARGET;
240+ adjustLatencyIfNeeded();
241+ }
242+ }
243+
244+ public int compareTo(LatencyRequest r) {
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+
257+
258+ /**
259+ * Makes a new request for a garbage-collection latency of the given
260+ * number of real-time milliseconds. A low-priority daemon thread makes a
261+ * best effort to ensure that the maximum object-inspection age never
262+ * exceeds the smallest of the currently active requests.
263+ *
264+ * @param latency
265+ * The requested latency
266+ *
267+ * @throws IllegalArgumentException
268+ * If the given <code>latency</code> is non-positive
269+ */
270+ public static LatencyRequest requestLatency(long latency) {
271+ return new LatencyRequest(latency);
272+ }
273+
274+
275+ /**
276+ * Returns the current smallest garbage-collection latency request, or zero
277+ * if there are no active requests.
278+ */
279+ public static long currentLatencyTarget() {
280+ long t = latencyTarget;
281+ return (t == NO_TARGET) ? 0 : t;
282+ }
283+
284+}