Path: blob/master/src/java.base/share/classes/jdk/internal/perf/Perf.java
41159 views
/*1* Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/24package jdk.internal.perf;2526import java.nio.ByteBuffer;27import java.security.Permission;28import java.security.PrivilegedAction;29import java.io.IOException;3031import sun.nio.cs.UTF_8;3233import jdk.internal.ref.CleanerFactory;3435/**36* The Perf class provides the ability to attach to an instrumentation37* buffer maintained by a Java virtual machine. The instrumentation38* buffer may be for the Java virtual machine running the methods of39* this class or it may be for another Java virtual machine on the40* same system.41* <p>42* In addition, this class provides methods to create instrumentation43* objects in the instrumentation buffer for the Java virtual machine44* that is running these methods. It also contains methods for acquiring45* the value of a platform specific high resolution clock for time46* stamp and interval measurement purposes.47*48* @author Brian Doherty49* @since 1.4.250* @see #getPerf51* @see jdk.internal.perf.Perf.GetPerfAction52* @see java.nio.ByteBuffer53*/54public final class Perf {5556private static Perf instance;5758private static final int PERF_MODE_RO = 0;59private static final int PERF_MODE_RW = 1;6061private Perf() { } // prevent instantiation6263/**64* The GetPerfAction class is a convenience class for acquiring access65* to the singleton Perf instance using the66* <code>AccessController.doPrivileged()</code> method.67* <p>68* An instance of this class can be used as the argument to69* <code>AccessController.doPrivileged(PrivilegedAction)</code>.70* <p> Here is a suggested idiom for use of this class:71*72* <blockquote><pre>{@code73* class MyTrustedClass {74* private static final Perf perf =75* AccessController.doPrivileged(new Perf.GetPerfAction<Perf>());76* ...77* }78* }</pre></blockquote>79* <p>80* In the presence of a security manager, the <code>MyTrustedClass</code>81* class in the above example will need to be granted the82* <em>"sun.misc.Perf.getPerf"</em> <code>RuntimePermission</code>83* permission in order to successfully acquire the singleton Perf instance.84* <p>85* Please note that the <em>"sun.misc.Perf.getPerf"</em> permission86* is not a JDK specified permission.87*88* @see java.security.AccessController#doPrivileged(PrivilegedAction)89* @see java.lang.RuntimePermission90*/91public static class GetPerfAction implements PrivilegedAction<Perf>92{93/**94* Run the <code>Perf.getPerf()</code> method in a privileged context.95*96* @see #getPerf97*/98public Perf run() {99return getPerf();100}101}102103/**104* Return a reference to the singleton Perf instance.105* <p>106* The getPerf() method returns the singleton instance of the Perf107* class. The returned object provides the caller with the capability108* for accessing the instrumentation buffer for this or another local109* Java virtual machine.110* <p>111* If a security manager is installed, its <code>checkPermission</code>112* method is called with a <code>RuntimePermission</code> with a target113* of <em>"sun.misc.Perf.getPerf"</em>. A security exception will result114* if the caller has not been granted this permission.115* <p>116* Access to the returned <code>Perf</code> object should be protected117* by its caller and not passed on to untrusted code. This object can118* be used to attach to the instrumentation buffer provided by this Java119* virtual machine or for those of other Java virtual machines running120* on the same system. The instrumentation buffer may contain senstitive121* information. API's built on top of this interface may want to provide122* finer grained access control to the contents of individual123* instrumentation objects contained within the buffer.124* <p>125* Please note that the <em>"sun.misc.Perf.getPerf"</em> permission126* is not a JDK specified permission.127*128* @return A reference to the singleton Perf instance.129* @throws SecurityException if a security manager exists and its130* <code>checkPermission</code> method doesn't allow access131* to the <em>"jdk.internal.perf.Perf.getPerf""</em> target.132* @see java.lang.RuntimePermission133* @see #attach134*/135public static Perf getPerf()136{137@SuppressWarnings("removal")138SecurityManager security = System.getSecurityManager();139if (security != null) {140Permission perm = new RuntimePermission("jdk.internal.perf.Perf.getPerf");141security.checkPermission(perm);142}143144return instance;145}146147/**148* Attach to the instrumentation buffer for the specified Java virtual149* machine.150* <p>151* This method will attach to the instrumentation buffer for the152* specified virtual machine. It returns a <code>ByteBuffer</code> object153* that is initialized to access the instrumentation buffer for the154* indicated Java virtual machine. The <code>lvmid</code> parameter is155* a integer value that uniquely identifies the target local Java virtual156* machine. It is typically, but not necessarily, the process id of157* the target Java virtual machine.158* <p>159* If the <code>lvmid</code> identifies a Java virtual machine different160* from the one running this method, then the coherency characteristics161* of the buffer are implementation dependent. Implementations that do162* not support named, coherent, shared memory may return a163* <code>ByteBuffer</code> object that contains only a snap shot of the164* data in the instrumentation buffer. Implementations that support named,165* coherent, shared memory, may return a <code>ByteBuffer</code> object166* that will be changing dynamically over time as the target Java virtual167* machine updates its mapping of this buffer.168* <p>169* If the <code>lvmid</code> is 0 or equal to the actual <code>lvmid</code>170* for the Java virtual machine running this method, then the returned171* <code>ByteBuffer</code> object will always be coherent and dynamically172* changing.173* <p>174* The attach mode specifies the access permissions requested for the175* instrumentation buffer of the target virtual machine. The permitted176* access permissions are:177* <ul>178* <li>"r" - Read only access. This Java virtual machine has only179* read access to the instrumentation buffer for the target Java180* virtual machine.181* <li>"rw" - Read/Write access. This Java virtual machine has read and182* write access to the instrumentation buffer for the target Java virtual183* machine. This mode is currently not supported and is reserved for184* future enhancements.185* </ul>186*187* @param lvmid an integer that uniquely identifies the188* target local Java virtual machine.189* @param mode a string indicating the attach mode.190* @return ByteBuffer a direct allocated byte buffer191* @throws IllegalArgumentException The lvmid or mode was invalid.192* @throws IOException An I/O error occurred while trying to acquire193* the instrumentation buffer.194* @throws OutOfMemoryError The instrumentation buffer could not be mapped195* into the virtual machine's address space.196* @see java.nio.ByteBuffer197*/198public ByteBuffer attach(int lvmid, String mode)199throws IllegalArgumentException, IOException200{201if (mode.compareTo("r") == 0) {202return attachImpl(null, lvmid, PERF_MODE_RO);203}204else if (mode.compareTo("rw") == 0) {205return attachImpl(null, lvmid, PERF_MODE_RW);206}207else {208throw new IllegalArgumentException("unknown mode");209}210}211212/**213* Attach to the instrumentation buffer for the specified Java virtual214* machine owned by the given user.215* <p>216* This method behaves just as the <code>attach(int lvmid, String mode)217* </code> method, except that it only searches for Java virtual machines218* owned by the specified user.219*220* @param user A <code>String</code> object containing the221* name of the user that owns the target Java222* virtual machine.223* @param lvmid an integer that uniquely identifies the224* target local Java virtual machine.225* @param mode a string indicating the attach mode.226* @return ByteBuffer a direct allocated byte buffer227* @throws IllegalArgumentException The lvmid or mode was invalid.228* @throws IOException An I/O error occurred while trying to acquire229* the instrumentation buffer.230* @throws OutOfMemoryError The instrumentation buffer could not be mapped231* into the virtual machine's address space.232* @see java.nio.ByteBuffer233*/234public ByteBuffer attach(String user, int lvmid, String mode)235throws IllegalArgumentException, IOException236{237if (mode.compareTo("r") == 0) {238return attachImpl(user, lvmid, PERF_MODE_RO);239}240else if (mode.compareTo("rw") == 0) {241return attachImpl(user, lvmid, PERF_MODE_RW);242}243else {244throw new IllegalArgumentException("unknown mode");245}246}247248/**249* Call the implementation specific attach method.250* <p>251* This method calls into the Java virtual machine to perform the platform252* specific attach method. Buffers returned from this method are253* internally managed as <code>PhantomRefereces</code> to provide for254* guaranteed, secure release of the native resources.255*256* @param user A <code>String</code> object containing the257* name of the user that owns the target Java258* virtual machine.259* @param lvmid an integer that uniquely identifies the260* target local Java virtual machine.261* @param mode a string indicating the attach mode.262* @return ByteBuffer a direct allocated byte buffer263* @throws IllegalArgumentException The lvmid or mode was invalid.264* @throws IOException An I/O error occurred while trying to acquire265* the instrumentation buffer.266* @throws OutOfMemoryError The instrumentation buffer could not be mapped267* into the virtual machine's address space.268*/269private ByteBuffer attachImpl(String user, int lvmid, int mode)270throws IllegalArgumentException, IOException271{272final ByteBuffer b = attach(user, lvmid, mode);273274if (lvmid == 0) {275// The native instrumentation buffer for this Java virtual276// machine is never unmapped.277return b;278}279else {280// This is an instrumentation buffer for another Java virtual281// machine with native resources that need to be managed. We282// create a duplicate of the native ByteBuffer and manage it283// with a Cleaner. When the duplicate becomes phantom reachable,284// the native resources will be released.285286final ByteBuffer dup = b.duplicate();287288CleanerFactory.cleaner()289.register(dup, new CleanerAction(instance, b));290return dup;291}292}293294private static class CleanerAction implements Runnable {295private final ByteBuffer bb;296private final Perf perf;297CleanerAction(Perf perf, ByteBuffer bb) {298this.perf = perf;299this.bb = bb;300}301public void run() {302try {303perf.detach(bb);304} catch (Throwable th) {305// avoid crashing the reference handler thread,306// but provide for some diagnosability307assert false : th.toString();308}309}310}311312/**313* Native method to perform the implementation specific attach mechanism.314* <p>315* The implementation of this method may return distinct or identical316* <code>ByteBuffer</code> objects for two distinct calls requesting317* attachment to the same Java virtual machine.318* <p>319* For the Sun HotSpot JVM, two distinct calls to attach to the same320* target Java virtual machine will result in two distinct ByteBuffer321* objects returned by this method. This may change in a future release.322*323* @param user A <code>String</code> object containing the324* name of the user that owns the target Java325* virtual machine.326* @param lvmid an integer that uniquely identifies the327* target local Java virtual machine.328* @param mode a string indicating the attach mode.329* @return ByteBuffer a direct allocated byte buffer330* @throws IllegalArgumentException The lvmid or mode was invalid.331* @throws IOException An I/O error occurred while trying to acquire332* the instrumentation buffer.333* @throws OutOfMemoryError The instrumentation buffer could not be mapped334* into the virtual machine's address space.335*/336private native ByteBuffer attach(String user, int lvmid, int mode)337throws IllegalArgumentException, IOException;338339/**340* Native method to perform the implementation specific detach mechanism.341* <p>342* If this method is passed a <code>ByteBuffer</code> object that is343* not created by the <code>attach</code> method, then the results of344* this method are undefined, with unpredictable and potentially damaging345* effects to the Java virtual machine. To prevent accidental or malicious346* use of this method, all native ByteBuffer created by the <code>347* attach</code> method are managed internally as PhantomReferences348* and resources are freed by the system.349* <p>350* If this method is passed a <code>ByteBuffer</code> object created351* by the <code>attach</code> method with a lvmid for the Java virtual352* machine running this method (lvmid=0, for example), then the detach353* request is silently ignored.354*355* @param bb A direct allocated byte buffer created by the356* <code>attach</code> method.357* @see java.nio.ByteBuffer358* @see #attach359*/360private native void detach(ByteBuffer bb);361362/**363* Create a <code>long</code> scalar entry in the instrumentation buffer364* with the given variability characteristic, units, and initial value.365* <p>366* Access to the instrument is provided through the returned <code>367* ByteBuffer</code> object. Typically, this object should be wrapped368* with <code>LongBuffer</code> view object.369*370* @param variability the variability characteristic for this entry.371* @param units the units for this entry.372* @param name the name of this entry.373* @param value the initial value for this entry.374* @return ByteBuffer a direct allocated ByteBuffer object that375* allows write access to a native memory location376* containing a <code>long</code> value.377*378* see sun.misc.perf.Variability379* see sun.misc.perf.Units380* @see java.nio.ByteBuffer381*/382public native ByteBuffer createLong(String name, int variability,383int units, long value);384385/**386* Create a <code>String</code> entry in the instrumentation buffer with387* the given variability characteristic, units, and initial value.388* <p>389* The maximum length of the <code>String</code> stored in this string390* instrument is given in by <code>maxLength</code> parameter. Updates391* to this instrument with <code>String</code> values with lengths greater392* than <code>maxLength</code> will be truncated to <code>maxLength</code>.393* The truncated value will be terminated by a null character.394* <p>395* The underlying implementation may further limit the length of the396* value, but will continue to preserve the null terminator.397* <p>398* Access to the instrument is provided through the returned <code>399* ByteBuffer</code> object.400*401* @param variability the variability characteristic for this entry.402* @param units the units for this entry.403* @param name the name of this entry.404* @param value the initial value for this entry.405* @param maxLength the maximum string length for this string406* instrument.407* @return ByteBuffer a direct allocated ByteBuffer that allows408* write access to a native memory location409* containing a <code>long</code> value.410*411* see sun.misc.perf.Variability412* see sun.misc.perf.Units413* @see java.nio.ByteBuffer414*/415public ByteBuffer createString(String name, int variability,416int units, String value, int maxLength)417{418byte[] v = value.getBytes(UTF_8.INSTANCE);419byte[] v1 = new byte[v.length+1];420System.arraycopy(v, 0, v1, 0, v.length);421v1[v.length] = '\0';422return createByteArray(name, variability, units, v1, Math.max(v1.length, maxLength));423}424425/**426* Create a <code>String</code> entry in the instrumentation buffer with427* the given variability characteristic, units, and initial value.428* <p>429* The maximum length of the <code>String</code> stored in this string430* instrument is implied by the length of the <code>value</code> parameter.431* Subsequent updates to the value of this instrument will be truncated432* to this implied maximum length. The truncated value will be terminated433* by a null character.434* <p>435* The underlying implementation may further limit the length of the436* initial or subsequent value, but will continue to preserve the null437* terminator.438* <p>439* Access to the instrument is provided through the returned <code>440* ByteBuffer</code> object.441*442* @param variability the variability characteristic for this entry.443* @param units the units for this entry.444* @param name the name of this entry.445* @param value the initial value for this entry.446* @return ByteBuffer a direct allocated ByteBuffer that allows447* write access to a native memory location448* containing a <code>long</code> value.449*450* see sun.misc.perf.Variability451* see sun.misc.perf.Units452* @see java.nio.ByteBuffer453*/454public ByteBuffer createString(String name, int variability,455int units, String value)456{457byte[] v = value.getBytes(UTF_8.INSTANCE);458byte[] v1 = new byte[v.length+1];459System.arraycopy(v, 0, v1, 0, v.length);460v1[v.length] = '\0';461return createByteArray(name, variability, units, v1, v1.length);462}463464/**465* Create a <code>byte</code> vector entry in the instrumentation buffer466* with the given variability characteristic, units, and initial value.467* <p>468* The <code>maxLength</code> parameter limits the size of the byte469* array instrument such that the initial or subsequent updates beyond470* this length are silently ignored. No special handling of truncated471* updates is provided.472* <p>473* The underlying implementation may further limit the length of the474* length of the initial or subsequent value.475* <p>476* Access to the instrument is provided through the returned <code>477* ByteBuffer</code> object.478*479* @param variability the variability characteristic for this entry.480* @param units the units for this entry.481* @param name the name of this entry.482* @param value the initial value for this entry.483* @param maxLength the maximum length of this byte array.484* @return ByteBuffer a direct allocated byte buffer that allows485* write access to a native memory location486* containing a <code>long</code> value.487*488* see sun.misc.perf.Variability489* see sun.misc.perf.Units490* @see java.nio.ByteBuffer491*/492public native ByteBuffer createByteArray(String name, int variability,493int units, byte[] value,494int maxLength);495496/**497* Return the value of the High Resolution Counter.498*499* The High Resolution Counter returns the number of ticks since500* since the start of the Java virtual machine. The resolution of501* the counter is machine dependent and can be determined from the502* value return by the {@link #highResFrequency} method.503*504* @return the number of ticks of machine dependent resolution since505* the start of the Java virtual machine.506*507* @see #highResFrequency508* @see java.lang.System#currentTimeMillis()509*/510public native long highResCounter();511512/**513* Returns the frequency of the High Resolution Counter, in ticks per514* second.515*516* This value can be used to convert the value of the High Resolution517* Counter, as returned from a call to the {@link #highResCounter} method,518* into the number of seconds since the start of the Java virtual machine.519*520* @return the frequency of the High Resolution Counter.521* @see #highResCounter522*/523public native long highResFrequency();524525private static native void registerNatives();526527static {528registerNatives();529instance = new Perf();530}531}532533534