Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.rmi/share/classes/sun/rmi/transport/GC.java
41154 views
1
/*
2
* Copyright (c) 1998, 2021, 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.rmi.transport;
27
28
import java.security.AccessController;
29
import java.security.PrivilegedAction;
30
import java.util.SortedSet;
31
import java.util.TreeSet;
32
import jdk.internal.misc.InnocuousThread;
33
34
35
/**
36
* Support for garbage-collection latency requests.
37
*
38
* @author Mark Reinhold
39
* @since 1.2
40
*/
41
42
@SuppressWarnings("removal")
43
class GC {
44
45
private GC() { } /* To prevent instantiation */
46
47
48
/* Latency-target value indicating that there's no active target
49
*/
50
private static final long NO_TARGET = Long.MAX_VALUE;
51
52
/* The current latency target, or NO_TARGET if there is no target
53
*/
54
private static long latencyTarget = NO_TARGET;
55
56
/* The daemon thread that implements the latency-target mechanism,
57
* or null if there is presently no daemon thread
58
*/
59
private static Thread daemon = null;
60
61
/* The lock object for the latencyTarget and daemon fields. The daemon
62
* thread, if it exists, waits on this lock for notification that the
63
* latency target has changed.
64
*/
65
private static class LatencyLock extends Object { };
66
private static Object lock = new LatencyLock();
67
68
69
/**
70
* Returns the maximum <em>object-inspection age</em>, which is the number
71
* of real-time milliseconds that have elapsed since the
72
* least-recently-inspected heap object was last inspected by the garbage
73
* collector.
74
*
75
* <p> For simple stop-the-world collectors this value is just the time
76
* since the most recent collection. For generational collectors it is the
77
* time since the oldest generation was most recently collected. Other
78
* collectors are free to return a pessimistic estimate of the elapsed
79
* time, or simply the time since the last full collection was performed.
80
*
81
* <p> Note that in the presence of reference objects, a given object that
82
* is no longer strongly reachable may have to be inspected multiple times
83
* before it can be reclaimed.
84
*/
85
public static native long maxObjectInspectionAge();
86
87
static {
88
AccessController.doPrivileged(new PrivilegedAction<Void>() {
89
public Void run() {
90
System.loadLibrary("rmi");
91
return null;
92
}});
93
}
94
95
private static class Daemon implements Runnable {
96
97
@Override
98
public void run() {
99
for (;;) {
100
long l;
101
synchronized (lock) {
102
103
l = latencyTarget;
104
if (l == NO_TARGET) {
105
/* No latency target, so exit */
106
GC.daemon = null;
107
return;
108
}
109
110
long d = maxObjectInspectionAge();
111
if (d >= l) {
112
/* Do a full collection. There is a remote possibility
113
* that a full collection will occurr between the time
114
* we sample the inspection age and the time the GC
115
* actually starts, but this is sufficiently unlikely
116
* that it doesn't seem worth the more expensive JVM
117
* interface that would be required.
118
*/
119
System.gc();
120
d = 0;
121
}
122
123
/* Wait for the latency period to expire,
124
* or for notification that the period has changed
125
*/
126
try {
127
lock.wait(l - d);
128
} catch (InterruptedException x) {
129
continue;
130
}
131
}
132
}
133
}
134
135
/* Create a new daemon thread */
136
public static void create() {
137
PrivilegedAction<Void> pa = new PrivilegedAction<Void>() {
138
public Void run() {
139
Thread t = InnocuousThread.newSystemThread("RMI GC Daemon",
140
new Daemon());
141
assert t.getContextClassLoader() == null;
142
t.setDaemon(true);
143
t.setPriority(Thread.MIN_PRIORITY + 1);
144
t.start();
145
GC.daemon = t;
146
return null;
147
}};
148
AccessController.doPrivileged(pa);
149
}
150
151
}
152
153
154
/* Sets the latency target to the given value.
155
* Must be invoked while holding the lock.
156
*/
157
private static void setLatencyTarget(long ms) {
158
latencyTarget = ms;
159
if (daemon == null) {
160
/* Create a new daemon thread */
161
Daemon.create();
162
} else {
163
/* Notify the existing daemon thread
164
* that the lateency target has changed
165
*/
166
lock.notify();
167
}
168
}
169
170
171
/**
172
* Represents an active garbage-collection latency request. Instances of
173
* this class are created by the <code>{@link #requestLatency}</code>
174
* method. Given a request, the only interesting operation is that of
175
* cancellation.
176
*/
177
public static class LatencyRequest
178
implements Comparable<LatencyRequest> {
179
180
/* Instance counter, used to generate unique identifers */
181
private static long counter = 0;
182
183
/* Sorted set of active latency requests */
184
private static SortedSet<LatencyRequest> requests = null;
185
186
/* Examine the request set and reset the latency target if necessary.
187
* Must be invoked while holding the lock.
188
*/
189
private static void adjustLatencyIfNeeded() {
190
if ((requests == null) || requests.isEmpty()) {
191
if (latencyTarget != NO_TARGET) {
192
setLatencyTarget(NO_TARGET);
193
}
194
} else {
195
LatencyRequest r = requests.first();
196
if (r.latency != latencyTarget) {
197
setLatencyTarget(r.latency);
198
}
199
}
200
}
201
202
/* The requested latency, or NO_TARGET
203
* if this request has been cancelled
204
*/
205
private long latency;
206
207
/* Unique identifier for this request */
208
private long id;
209
210
private LatencyRequest(long ms) {
211
if (ms <= 0) {
212
throw new IllegalArgumentException("Non-positive latency: "
213
+ ms);
214
}
215
this.latency = ms;
216
synchronized (lock) {
217
this.id = ++counter;
218
if (requests == null) {
219
requests = new TreeSet<LatencyRequest>();
220
}
221
requests.add(this);
222
adjustLatencyIfNeeded();
223
}
224
}
225
226
/**
227
* Cancels this latency request.
228
*
229
* @throws IllegalStateException
230
* If this request has already been cancelled
231
*/
232
public void cancel() {
233
synchronized (lock) {
234
if (this.latency == NO_TARGET) {
235
throw new IllegalStateException("Request already"
236
+ " cancelled");
237
}
238
if (!requests.remove(this)) {
239
throw new InternalError("Latency request "
240
+ this + " not found");
241
}
242
if (requests.isEmpty()) requests = null;
243
this.latency = NO_TARGET;
244
adjustLatencyIfNeeded();
245
}
246
}
247
248
public int compareTo(LatencyRequest r) {
249
long d = this.latency - r.latency;
250
if (d == 0) d = this.id - r.id;
251
return (d < 0) ? -1 : ((d > 0) ? +1 : 0);
252
}
253
254
public String toString() {
255
return (LatencyRequest.class.getName()
256
+ "[" + latency + "," + id + "]");
257
}
258
259
}
260
261
262
/**
263
* Makes a new request for a garbage-collection latency of the given
264
* number of real-time milliseconds. A low-priority daemon thread makes a
265
* best effort to ensure that the maximum object-inspection age never
266
* exceeds the smallest of the currently active requests.
267
*
268
* @param latency
269
* The requested latency
270
*
271
* @throws IllegalArgumentException
272
* If the given <code>latency</code> is non-positive
273
*/
274
public static LatencyRequest requestLatency(long latency) {
275
return new LatencyRequest(latency);
276
}
277
278
279
/**
280
* Returns the current smallest garbage-collection latency request, or zero
281
* if there are no active requests.
282
*/
283
public static long currentLatencyTarget() {
284
long t = latencyTarget;
285
return (t == NO_TARGET) ? 0 : t;
286
}
287
288
}
289
290