|
1 /* |
|
2 * Copyright 2002-2006 Sun Microsystems, Inc. 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. Sun designates this |
|
8 * particular file as subject to the "Classpath" exception as provided |
|
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
|
22 * CA 95054 USA or visit www.sun.com if you need additional information or |
|
23 * have any questions. |
|
24 */ |
|
25 package sun.misc; |
|
26 |
|
27 import java.nio.ByteBuffer; |
|
28 import java.security.Permission; |
|
29 import java.security.PrivilegedAction; |
|
30 import java.io.IOException; |
|
31 import java.io.UnsupportedEncodingException; |
|
32 |
|
33 /** |
|
34 * The Perf class provides the ability to attach to an instrumentation |
|
35 * buffer maintained by a Java virtual machine. The instrumentation |
|
36 * buffer may be for the Java virtual machine running the methods of |
|
37 * this class or it may be for another Java virtual machine on the |
|
38 * same system. |
|
39 * <p> |
|
40 * In addition, this class provides methods to create instrumentation |
|
41 * objects in the instrumentation buffer for the Java virtual machine |
|
42 * that is running these methods. It also contains methods for acquiring |
|
43 * the value of a platform specific high resolution clock for time |
|
44 * stamp and interval measurement purposes. |
|
45 * |
|
46 * @author Brian Doherty |
|
47 * @since 1.4.2 |
|
48 * @see #getPerf |
|
49 * @see sun.misc.Perf$GetPerfAction |
|
50 * @see java.nio.ByteBuffer |
|
51 */ |
|
52 public final class Perf { |
|
53 |
|
54 private static Perf instance; |
|
55 |
|
56 private static final int PERF_MODE_RO = 0; |
|
57 private static final int PERF_MODE_RW = 1; |
|
58 |
|
59 private Perf() { } // prevent instantiation |
|
60 |
|
61 /** |
|
62 * The GetPerfAction class is a convenience class for acquiring access |
|
63 * to the singleton Perf instance using the |
|
64 * <code>AccessController.doPrivileged()</code> method. |
|
65 * <p> |
|
66 * An instance of this class can be used as the argument to |
|
67 * <code>AccessController.doPrivileged(PrivilegedAction)</code>. |
|
68 * <p> Here is a suggested idiom for use of this class: |
|
69 * |
|
70 * <blockquote><pre> |
|
71 * class MyTrustedClass { |
|
72 * private static final Perf perf = |
|
73 * AccessController.doPrivileged(new Perf.GetPerfAction<Perf>()); |
|
74 * ... |
|
75 * } |
|
76 * </pre></blockquote> |
|
77 * <p> |
|
78 * In the presence of a security manager, the <code>MyTrustedClass</code> |
|
79 * class in the above example will need to be granted the |
|
80 * <em>"sun.misc.Perf.getPerf"</em> <code>RuntimePermission</code> |
|
81 * permission in order to successfully acquire the singleton Perf instance. |
|
82 * <p> |
|
83 * Please note that the <em>"sun.misc.Perf.getPerf"</em> permission |
|
84 * is not a JDK specified permission. |
|
85 * |
|
86 * @see java.security.AccessController#doPrivileged(PrivilegedAction) |
|
87 * @see java.lang.RuntimePermission |
|
88 */ |
|
89 public static class GetPerfAction implements PrivilegedAction<Perf> |
|
90 { |
|
91 /** |
|
92 * Run the <code>Perf.getPerf()</code> method in a privileged context. |
|
93 * |
|
94 * @see #getPerf |
|
95 */ |
|
96 public Perf run() { |
|
97 return getPerf(); |
|
98 } |
|
99 } |
|
100 |
|
101 /** |
|
102 * Return a reference to the singleton Perf instance. |
|
103 * <p> |
|
104 * The getPerf() method returns the singleton instance of the Perf |
|
105 * class. The returned object provides the caller with the capability |
|
106 * for accessing the instrumentation buffer for this or another local |
|
107 * Java virtual machine. |
|
108 * <p> |
|
109 * If a security manager is installed, its <code>checkPermission</code> |
|
110 * method is called with a <code>RuntimePermission</code> with a target |
|
111 * of <em>"sun.misc.Perf.getPerf"</em>. A security exception will result |
|
112 * if the caller has not been granted this permission. |
|
113 * <p> |
|
114 * Access to the returned <code>Perf</code> object should be protected |
|
115 * by its caller and not passed on to untrusted code. This object can |
|
116 * be used to attach to the instrumentation buffer provided by this Java |
|
117 * virtual machine or for those of other Java virtual machines running |
|
118 * on the same system. The instrumentation buffer may contain senstitive |
|
119 * information. API's built on top of this interface may want to provide |
|
120 * finer grained access control to the contents of individual |
|
121 * instrumentation objects contained within the buffer. |
|
122 * <p> |
|
123 * Please note that the <em>"sun.misc.Perf.getPerf"</em> permission |
|
124 * is not a JDK specified permission. |
|
125 * |
|
126 * @return A reference to the singleton Perf instance. |
|
127 * @throws AccessControlException if a security manager exists and |
|
128 * its <code>checkPermission</code> method doesn't allow |
|
129 * access to the <em>"sun.misc.Perf.getPerf"</em> target. |
|
130 * @see java.lang.RuntimePermission |
|
131 * @see #attach |
|
132 */ |
|
133 public static Perf getPerf() |
|
134 { |
|
135 SecurityManager security = System.getSecurityManager(); |
|
136 if (security != null) { |
|
137 Permission perm = new RuntimePermission("sun.misc.Perf.getPerf"); |
|
138 security.checkPermission(perm); |
|
139 } |
|
140 |
|
141 return instance; |
|
142 } |
|
143 |
|
144 /** |
|
145 * Attach to the instrumentation buffer for the specified Java virtual |
|
146 * machine. |
|
147 * <p> |
|
148 * This method will attach to the instrumentation buffer for the |
|
149 * specified virtual machine. It returns a <code>ByteBuffer</code> object |
|
150 * that is initialized to access the instrumentation buffer for the |
|
151 * indicated Java virtual machine. The <code>lvmid</code> parameter is |
|
152 * a integer value that uniquely identifies the target local Java virtual |
|
153 * machine. It is typically, but not necessarily, the process id of |
|
154 * the target Java virtual machine. |
|
155 * <p> |
|
156 * If the <code>lvmid</code> identifies a Java virtual machine different |
|
157 * from the one running this method, then the coherency characteristics |
|
158 * of the buffer are implementation dependent. Implementations that do |
|
159 * not support named, coherent, shared memory may return a |
|
160 * <code>ByteBuffer</code> object that contains only a snap shot of the |
|
161 * data in the instrumentation buffer. Implementations that support named, |
|
162 * coherent, shared memory, may return a <code>ByteBuffer</code> object |
|
163 * that will be changing dynamically over time as the target Java virtual |
|
164 * machine updates its mapping of this buffer. |
|
165 * <p> |
|
166 * If the <code>lvmid</code> is 0 or equal to the actual <code>lvmid</code> |
|
167 * for the Java virtual machine running this method, then the returned |
|
168 * <code>ByteBuffer</code> object will always be coherent and dynamically |
|
169 * changing. |
|
170 * <p> |
|
171 * The attach mode specifies the access permissions requested for the |
|
172 * instrumentation buffer of the target virtual machine. The permitted |
|
173 * access permissions are: |
|
174 * <p> |
|
175 * <bl> |
|
176 * <li>"r" - Read only access. This Java virtual machine has only |
|
177 * read access to the instrumentation buffer for the target Java |
|
178 * virtual machine. |
|
179 * <li>"rw" - Read/Write access. This Java virtual machine has read and |
|
180 * write access to the instrumentation buffer for the target Java virtual |
|
181 * machine. This mode is currently not supported and is reserved for |
|
182 * future enhancements. |
|
183 * </bl> |
|
184 * |
|
185 * @param lvmid an integer that uniquely identifies the |
|
186 * target local Java virtual machine. |
|
187 * @param mode a string indicating the attach mode. |
|
188 * @return ByteBuffer a direct allocated byte buffer |
|
189 * @throws IllegalArgumentException The lvmid or mode was invalid. |
|
190 * @throws IOException An I/O error occurred while trying to acquire |
|
191 * the instrumentation buffer. |
|
192 * @throws OutOfMemoryError The instrumentation buffer could not be mapped |
|
193 * into the virtual machine's address space. |
|
194 * @see java.nio.ByteBuffer |
|
195 */ |
|
196 public ByteBuffer attach(int lvmid, String mode) |
|
197 throws IllegalArgumentException, IOException |
|
198 { |
|
199 if (mode.compareTo("r") == 0) { |
|
200 return attachImpl(null, lvmid, PERF_MODE_RO); |
|
201 } |
|
202 else if (mode.compareTo("rw") == 0) { |
|
203 return attachImpl(null, lvmid, PERF_MODE_RW); |
|
204 } |
|
205 else { |
|
206 throw new IllegalArgumentException("unknown mode"); |
|
207 } |
|
208 } |
|
209 |
|
210 /** |
|
211 * Attach to the instrumentation buffer for the specified Java virtual |
|
212 * machine owned by the given user. |
|
213 * <p> |
|
214 * This method behaves just as the <code>attach(int lvmid, String mode) |
|
215 * </code> method, except that it only searches for Java virtual machines |
|
216 * owned by the specified user. |
|
217 * |
|
218 * @param user A <code>String</code> object containing the |
|
219 * name of the user that owns the target Java |
|
220 * virtual machine. |
|
221 * @param lvmid an integer that uniquely identifies the |
|
222 * target local Java virtual machine. |
|
223 * @param mode a string indicating the attach mode. |
|
224 * @return ByteBuffer a direct allocated byte buffer |
|
225 * @throws IllegalArgumentException The lvmid or mode was invalid. |
|
226 * @throws IOException An I/O error occurred while trying to acquire |
|
227 * the instrumentation buffer. |
|
228 * @throws OutOfMemoryError The instrumentation buffer could not be mapped |
|
229 * into the virtual machine's address space. |
|
230 * @see java.nio.ByteBuffer |
|
231 */ |
|
232 public ByteBuffer attach(String user, int lvmid, String mode) |
|
233 throws IllegalArgumentException, IOException |
|
234 { |
|
235 if (mode.compareTo("r") == 0) { |
|
236 return attachImpl(user, lvmid, PERF_MODE_RO); |
|
237 } |
|
238 else if (mode.compareTo("rw") == 0) { |
|
239 return attachImpl(user, lvmid, PERF_MODE_RW); |
|
240 } |
|
241 else { |
|
242 throw new IllegalArgumentException("unknown mode"); |
|
243 } |
|
244 } |
|
245 |
|
246 /** |
|
247 * Call the implementation specific attach method. |
|
248 * <p> |
|
249 * This method calls into the Java virtual machine to perform the platform |
|
250 * specific attach method. Buffers returned from this method are |
|
251 * internally managed as <code>PhantomRefereces</code> to provide for |
|
252 * guaranteed, secure release of the native resources. |
|
253 * |
|
254 * @param user A <code>String</code> object containing the |
|
255 * name of the user that owns the target Java |
|
256 * virtual machine. |
|
257 * @param lvmid an integer that uniquely identifies the |
|
258 * target local Java virtual machine. |
|
259 * @param mode a string indicating the attach mode. |
|
260 * @return ByteBuffer a direct allocated byte buffer |
|
261 * @throws IllegalArgumentException The lvmid or mode was invalid. |
|
262 * @throws IOException An I/O error occurred while trying to acquire |
|
263 * the instrumentation buffer. |
|
264 * @throws OutOfMemoryError The instrumentation buffer could not be mapped |
|
265 * into the virtual machine's address space. |
|
266 */ |
|
267 private ByteBuffer attachImpl(String user, int lvmid, int mode) |
|
268 throws IllegalArgumentException, IOException |
|
269 { |
|
270 final ByteBuffer b = attach(user, lvmid, mode); |
|
271 |
|
272 if (lvmid == 0) { |
|
273 // The native instrumentation buffer for this Java virtual |
|
274 // machine is never unmapped. |
|
275 return b; |
|
276 } |
|
277 else { |
|
278 // This is an instrumentation buffer for another Java virtual |
|
279 // machine with native resources that need to be managed. We |
|
280 // create a duplicate of the native ByteBuffer and manage it |
|
281 // with a Cleaner object (PhantomReference). When the duplicate |
|
282 // becomes only phantomly reachable, the native resources will |
|
283 // be released. |
|
284 |
|
285 final ByteBuffer dup = b.duplicate(); |
|
286 Cleaner.create(dup, new Runnable() { |
|
287 public void run() { |
|
288 try { |
|
289 instance.detach(b); |
|
290 } |
|
291 catch (Throwable th) { |
|
292 // avoid crashing the reference handler thread, |
|
293 // but provide for some diagnosability |
|
294 assert false : th.toString(); |
|
295 } |
|
296 } |
|
297 }); |
|
298 return dup; |
|
299 } |
|
300 } |
|
301 |
|
302 /** |
|
303 * Native method to perform the implementation specific attach mechanism. |
|
304 * <p> |
|
305 * The implementation of this method may return distinct or identical |
|
306 * <code>ByteBuffer</code> objects for two distinct calls requesting |
|
307 * attachment to the same Java virtual machine. |
|
308 * <p> |
|
309 * For the Sun HotSpot JVM, two distinct calls to attach to the same |
|
310 * target Java virtual machine will result in two distinct ByteBuffer |
|
311 * objects returned by this method. This may change in a future release. |
|
312 * |
|
313 * @param user A <code>String</code> object containing the |
|
314 * name of the user that owns the target Java |
|
315 * virtual machine. |
|
316 * @param lvmid an integer that uniquely identifies the |
|
317 * target local Java virtual machine. |
|
318 * @param mode a string indicating the attach mode. |
|
319 * @return ByteBuffer a direct allocated byte buffer |
|
320 * @throws IllegalArgumentException The lvmid or mode was invalid. |
|
321 * @throws IOException An I/O error occurred while trying to acquire |
|
322 * the instrumentation buffer. |
|
323 * @throws OutOfMemoryError The instrumentation buffer could not be mapped |
|
324 * into the virtual machine's address space. |
|
325 */ |
|
326 private native ByteBuffer attach(String user, int lvmid, int mode) |
|
327 throws IllegalArgumentException, IOException; |
|
328 |
|
329 /** |
|
330 * Native method to perform the implementation specific detach mechanism. |
|
331 * <p> |
|
332 * If this method is passed a <code>ByteBuffer</code> object that is |
|
333 * not created by the <code>attach</code> method, then the results of |
|
334 * this method are undefined, with unpredictable and potentially damaging |
|
335 * effects to the Java virtual machine. To prevent accidental or malicious |
|
336 * use of this method, all native ByteBuffer created by the <code> |
|
337 * attach</code> method are managed internally as PhantomReferences |
|
338 * and resources are freed by the system. |
|
339 * <p> |
|
340 * If this method is passed a <code>ByteBuffer</code> object created |
|
341 * by the <code>attach</code> method with a lvmid for the Java virtual |
|
342 * machine running this method (lvmid=0, for example), then the detach |
|
343 * request is silently ignored. |
|
344 * |
|
345 * @param ByteBuffer A direct allocated byte buffer created by the |
|
346 * <code>attach</code> method. |
|
347 * @see java.nio.ByteBuffer |
|
348 * @see #attach |
|
349 */ |
|
350 private native void detach(ByteBuffer bb); |
|
351 |
|
352 /** |
|
353 * Create a <code>long</code> scalar entry in the instrumentation buffer |
|
354 * with the given variability characteristic, units, and initial value. |
|
355 * <p> |
|
356 * Access to the instrument is provided through the returned <code> |
|
357 * ByteBuffer</code> object. Typically, this object should be wrapped |
|
358 * with <code>LongBuffer</code> view object. |
|
359 * |
|
360 * @param variability the variability characteristic for this entry. |
|
361 * @param units the units for this entry. |
|
362 * @param name the name of this entry. |
|
363 * @param value the initial value for this entry. |
|
364 * @return ByteBuffer a direct allocated ByteBuffer object that |
|
365 * allows write access to a native memory location |
|
366 * containing a <code>long</code> value. |
|
367 * |
|
368 * see sun.misc.perf.Variability |
|
369 * see sun.misc.perf.Units |
|
370 * @see java.nio.ByteBuffer |
|
371 */ |
|
372 public native ByteBuffer createLong(String name, int variability, |
|
373 int units, long value); |
|
374 |
|
375 /** |
|
376 * Create a <code>String</code> entry in the instrumentation buffer with |
|
377 * the given variability characteristic, units, and initial value. |
|
378 * <p> |
|
379 * The maximum length of the <code>String</code> stored in this string |
|
380 * instrument is given in by <code>maxLength</code> parameter. Updates |
|
381 * to this instrument with <code>String</code> values with lengths greater |
|
382 * than <code>maxLength</code> will be truncated to <code>maxLength</code>. |
|
383 * The truncated value will be terminated by a null character. |
|
384 * <p> |
|
385 * The underlying implementation may further limit the length of the |
|
386 * value, but will continue to preserve the null terminator. |
|
387 * <p> |
|
388 * Access to the instrument is provided through the returned <code> |
|
389 * ByteBuffer</code> object. |
|
390 * |
|
391 * @param variability the variability characteristic for this entry. |
|
392 * @param units the units for this entry. |
|
393 * @param name the name of this entry. |
|
394 * @param value the initial value for this entry. |
|
395 * @param maxLength the maximum string length for this string |
|
396 * instrument. |
|
397 * @return ByteBuffer a direct allocated ByteBuffer that allows |
|
398 * write access to a native memory location |
|
399 * containing a <code>long</code> value. |
|
400 * |
|
401 * see sun.misc.perf.Variability |
|
402 * see sun.misc.perf.Units |
|
403 * @see java.nio.ByteBuffer |
|
404 */ |
|
405 public ByteBuffer createString(String name, int variability, |
|
406 int units, String value, int maxLength) |
|
407 { |
|
408 byte[] v = getBytes(value); |
|
409 byte[] v1 = new byte[v.length+1]; |
|
410 System.arraycopy(v, 0, v1, 0, v.length); |
|
411 v1[v.length] = '\0'; |
|
412 return createByteArray(name, variability, units, v1, Math.max(v1.length, maxLength)); |
|
413 } |
|
414 |
|
415 /** |
|
416 * Create a <code>String</code> entry in the instrumentation buffer with |
|
417 * the given variability characteristic, units, and initial value. |
|
418 * <p> |
|
419 * The maximum length of the <code>String</code> stored in this string |
|
420 * instrument is implied by the length of the <code>value</code> parameter. |
|
421 * Subsequent updates to the value of this instrument will be truncated |
|
422 * to this implied maximum length. The truncated value will be terminated |
|
423 * by a null character. |
|
424 * <p> |
|
425 * The underlying implementation may further limit the length of the |
|
426 * initial or subsequent value, but will continue to preserve the null |
|
427 * terminator. |
|
428 * <p> |
|
429 * Access to the instrument is provided through the returned <code> |
|
430 * ByteBuffer</code> object. |
|
431 * |
|
432 * @param variability the variability characteristic for this entry. |
|
433 * @param units the units for this entry. |
|
434 * @param name the name of this entry. |
|
435 * @param value the initial value for this entry. |
|
436 * @return ByteBuffer a direct allocated ByteBuffer that allows |
|
437 * write access to a native memory location |
|
438 * containing a <code>long</code> value. |
|
439 * |
|
440 * see sun.misc.perf.Variability |
|
441 * see sun.misc.perf.Units |
|
442 * @see java.nio.ByteBuffer |
|
443 */ |
|
444 public ByteBuffer createString(String name, int variability, |
|
445 int units, String value) |
|
446 { |
|
447 byte[] v = getBytes(value); |
|
448 byte[] v1 = new byte[v.length+1]; |
|
449 System.arraycopy(v, 0, v1, 0, v.length); |
|
450 v1[v.length] = '\0'; |
|
451 return createByteArray(name, variability, units, v1, v1.length); |
|
452 } |
|
453 |
|
454 /** |
|
455 * Create a <code>byte</code> vector entry in the instrumentation buffer |
|
456 * with the given variability characteristic, units, and initial value. |
|
457 * <p> |
|
458 * The <code>maxLength</code> parameter limits the size of the byte |
|
459 * array instrument such that the initial or subsequent updates beyond |
|
460 * this length are silently ignored. No special handling of truncated |
|
461 * updates is provided. |
|
462 * <p> |
|
463 * The underlying implementation may further limit the length of the |
|
464 * length of the initial or subsequent value. |
|
465 * <p> |
|
466 * Access to the instrument is provided through the returned <code> |
|
467 * ByteBuffer</code> object. |
|
468 * |
|
469 * @param variability the variability characteristic for this entry. |
|
470 * @param units the units for this entry. |
|
471 * @param name the name of this entry. |
|
472 * @param value the initial value for this entry. |
|
473 * @param maxLength the maximum length of this byte array. |
|
474 * @return ByteBuffer a direct allocated byte buffer that allows |
|
475 * write access to a native memory location |
|
476 * containing a <code>long</code> value. |
|
477 * |
|
478 * see sun.misc.perf.Variability |
|
479 * see sun.misc.perf.Units |
|
480 * @see java.nio.ByteBuffer |
|
481 */ |
|
482 public native ByteBuffer createByteArray(String name, int variability, |
|
483 int units, byte[] value, |
|
484 int maxLength); |
|
485 |
|
486 |
|
487 /** |
|
488 * convert string to an array of UTF-8 bytes |
|
489 */ |
|
490 private static byte[] getBytes(String s) |
|
491 { |
|
492 byte[] bytes = null; |
|
493 |
|
494 try { |
|
495 bytes = s.getBytes("UTF-8"); |
|
496 } |
|
497 catch (UnsupportedEncodingException e) { |
|
498 // ignore, UTF-8 encoding is always known |
|
499 } |
|
500 |
|
501 return bytes; |
|
502 } |
|
503 |
|
504 /** |
|
505 * Return the value of the High Resolution Counter. |
|
506 * |
|
507 * The High Resolution Counter returns the number of ticks since |
|
508 * since the start of the Java virtual machine. The resolution of |
|
509 * the counter is machine dependent and can be determined from the |
|
510 * value return by the {@link #highResFrequency} method. |
|
511 * |
|
512 * @return the number of ticks of machine dependent resolution since |
|
513 * the start of the Java virtual machine. |
|
514 * |
|
515 * @see #highResFrequency |
|
516 * @see java.lang.System#currentTimeMillis() |
|
517 */ |
|
518 public native long highResCounter(); |
|
519 |
|
520 /** |
|
521 * Returns the frequency of the High Resolution Counter, in ticks per |
|
522 * second. |
|
523 * |
|
524 * This value can be used to convert the value of the High Resolution |
|
525 * Counter, as returned from a call to the {@link #highResCounter} method, |
|
526 * into the number of seconds since the start of the Java virtual machine. |
|
527 * |
|
528 * @return the frequency of the High Resolution Counter. |
|
529 * @see #highResCounter |
|
530 */ |
|
531 public native long highResFrequency(); |
|
532 |
|
533 private static native void registerNatives(); |
|
534 |
|
535 static { |
|
536 registerNatives(); |
|
537 instance = new Perf(); |
|
538 } |
|
539 } |