/*
 * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package jdk.jfr.internal;

import java.io.IOException;
import java.util.List;

import jdk.internal.HotSpotIntrinsicCandidate;
import jdk.jfr.Event;

Interface against the JVM.
/** * Interface against the JVM. * */
public final class JVM { private static final JVM jvm = new JVM(); // JVM signals file changes by doing Object#notifu on this object static final Object FILE_DELTA_CHANGE = new Object(); static final long RESERVED_CLASS_ID_LIMIT = 400; private volatile boolean recording; private volatile boolean nativeOK; private static native void registerNatives(); static { registerNatives(); for (LogTag tag : LogTag.values()) { subscribeLogLevel(tag, tag.id); } Options.ensureInitialized(); }
Get the one and only JVM.
Returns:the JVM
/** * Get the one and only JVM. * * @return the JVM */
public static JVM getJVM() { return jvm; } private JVM() { }
Begin recording events Requires that JFR has been started with createNativeJFR()
/** * Begin recording events * * Requires that JFR has been started with {@link #createNativeJFR()} */
public native void beginRecording();
Return ticks
Returns:the time, in ticks
/** * Return ticks * * @return the time, in ticks * */
@HotSpotIntrinsicCandidate public static native long counterTime();
Emits native periodic event.
Params:
  • eventTypeId – type id
  • timestamp – commit time for event
  • when – when it is being done When
Returns:true if the event was committed
/** * Emits native periodic event. * * @param eventTypeId type id * * @param timestamp commit time for event * @param when when it is being done {@link Periodic.When} * * @return true if the event was committed */
public native boolean emitEvent(long eventTypeId, long timestamp, long when);
End recording events, which includes flushing data in thread buffers Requires that JFR has been started with createNativeJFR()
/** * End recording events, which includes flushing data in thread buffers * * Requires that JFR has been started with {@link #createNativeJFR()} * */
public native void endRecording();
Return a list of all classes deriving from Event
Returns:list of event classes.
/** * Return a list of all classes deriving from {@link jdk.internal.event.Event} * * @return list of event classes. */
public native List<Class<? extends jdk.internal.event.Event>> getAllEventClasses();
Return a count of the number of unloaded classes deriving from Event
Returns:number of unloaded event classes.
/** * Return a count of the number of unloaded classes deriving from {@link Event} * * @return number of unloaded event classes. */
public native long getUnloadedEventClassCount();
Return a unique identifier for a class. The class is marked as being "in use" in JFR.
Params:
  • clazz – clazz
Returns:a unique class identifier
/** * Return a unique identifier for a class. The class is marked as being * "in use" in JFR. * * @param clazz clazz * * @return a unique class identifier */
@HotSpotIntrinsicCandidate public static native long getClassId(Class<?> clazz); // temporary workaround until we solve intrinsics supporting epoch shift tagging public static native long getClassIdNonIntrinsic(Class<?> clazz);
Return process identifier.
Returns:process identifier
/** * Return process identifier. * * @return process identifier */
public native String getPid();
Return unique identifier for stack trace. Requires that JFR has been started with createNativeJFR()
Params:
  • skipCount – number of frames to skip
Returns:a unique stack trace identifier
/** * Return unique identifier for stack trace. * * Requires that JFR has been started with {@link #createNativeJFR()} * * @param skipCount number of frames to skip * @return a unique stack trace identifier */
public native long getStackTraceId(int skipCount);
Return identifier for thread
Params:
  • t – thread
Returns:a unique thread identifier
/** * Return identifier for thread * * @param t thread * @return a unique thread identifier */
public native long getThreadId(Thread t);
Frequency, ticks per second
Returns:frequency
/** * Frequency, ticks per second * * @return frequency */
public native long getTicksFrequency();
Write message to log. Should swallow null or empty message, and be able to handle any Java character and not crash with very large message
Params:
  • tagSetId – the tagset id
  • level – on level
  • message – log message
/** * Write message to log. Should swallow null or empty message, and be able * to handle any Java character and not crash with very large message * * @param tagSetId the tagset id * @param level on level * @param message log message * */
public static native void log(int tagSetId, int level, String message);
Subscribe to LogLevel updates for LogTag
Params:
  • lt – the log tag to subscribe
  • tagSetId – the tagset id
/** * Subscribe to LogLevel updates for LogTag * * @param lt the log tag to subscribe * @param tagSetId the tagset id */
public static native void subscribeLogLevel(LogTag lt, int tagSetId);
Call to invoke event tagging and retransformation of the passed classes
Params:
  • classes –
Throws:
/** * Call to invoke event tagging and retransformation of the passed classes * * @param classes * * @throws IllegalStateException if wrong JVMTI phase. */
public native synchronized void retransformClasses(Class<?>[] classes);
Enable event
Params:
  • eventTypeId – event type id
  • enabled – enable event
/** * Enable event * * @param eventTypeId event type id * * @param enabled enable event */
public native void setEnabled(long eventTypeId, boolean enabled);
Interval at which the JVM should notify on FILE_DELTA_CHANGE
Params:
  • delta – number of bytes, reset after file rotation
/** * Interval at which the JVM should notify on {@link #FILE_DELTA_CHANGE} * * @param delta number of bytes, reset after file rotation */
public native void setFileNotification(long delta);
Set the number of global buffers to use
Params:
  • count –
Throws:
/** * Set the number of global buffers to use * * @param count * * @throws IllegalArgumentException if count is not within a valid range * @throws IllegalStateException if value can't be changed */
public native void setGlobalBufferCount(long count) throws IllegalArgumentException, IllegalStateException;
Set size of a global buffer
Params:
  • size –
Throws:
/** * Set size of a global buffer * * @param size * * @throws IllegalArgumentException if buffer size is not within a valid * range */
public native void setGlobalBufferSize(long size) throws IllegalArgumentException;
Set overall memory size
Params:
  • size –
Throws:
/** * Set overall memory size * * @param size * * @throws IllegalArgumentException if memory size is not within a valid * range */
public native void setMemorySize(long size) throws IllegalArgumentException;
/** Set interval for method samples, in milliseconds. Setting interval to 0 turns off the method sampler.
Params:
  • intervalMillis – the sampling interval
/** /** * Set interval for method samples, in milliseconds. * * Setting interval to 0 turns off the method sampler. * * @param intervalMillis the sampling interval */
public native void setMethodSamplingInterval(long type, long intervalMillis);
Sets the file where data should be written. Requires that JFR has been started with createNativeJFR()
Recording Previous Current Action ============================================== true null null Ignore, keep recording in-memory true null file1 Start disk recording true file null Copy out metadata to disk and continue in-memory recording true file1 file2 Copy out metadata and start with new File (file2) false * null Ignore, but start recording to memory with beginRecording() false * file Ignore, but start recording to disk with beginRecording() 
recording can be set to true/false with beginRecording() endRecording()
Params:
  • file – the file where data should be written, or null if it should not be copied out (in memory).
Throws:
/** * Sets the file where data should be written. * * Requires that JFR has been started with {@link #createNativeJFR()} * * <pre> * Recording Previous Current Action * ============================================== * true null null Ignore, keep recording in-memory * true null file1 Start disk recording * true file null Copy out metadata to disk and continue in-memory recording * true file1 file2 Copy out metadata and start with new File (file2) * false * null Ignore, but start recording to memory with {@link #beginRecording()} * false * file Ignore, but start recording to disk with {@link #beginRecording()} * * </pre> * * recording can be set to true/false with {@link #beginRecording()} * {@link #endRecording()} * * @param file the file where data should be written, or null if it should * not be copied out (in memory). * * @throws IOException */
public native void setOutput(String file);
Controls if a class deriving from jdk.jfr.Event should always be instrumented on class load.
@paramforce, true to force initialization, false otherwise
/** * Controls if a class deriving from jdk.jfr.Event should * always be instrumented on class load. * * @param force, true to force initialization, false otherwise */
public native void setForceInstrumentation(boolean force);
Turn on/off thread sampling.
Params:
  • sampleThreads – true if threads should be sampled, false otherwise.
Throws:
/** * Turn on/off thread sampling. * * @param sampleThreads true if threads should be sampled, false otherwise. * * @throws IllegalStateException if state can't be changed. */
public native void setSampleThreads(boolean sampleThreads) throws IllegalStateException;
Turn on/off compressed integers.
Params:
  • compressed – true if compressed integers should be used, false otherwise.
Throws:
/** * Turn on/off compressed integers. * * @param compressed true if compressed integers should be used, false * otherwise. * * @throws IllegalStateException if state can't be changed. */
public native void setCompressedIntegers(boolean compressed) throws IllegalStateException;
Set stack depth.
Params:
  • depth –
Throws:
/** * Set stack depth. * * @param depth * * @throws IllegalArgumentException if not within a valid range * @throws IllegalStateException if depth can't be changed */
public native void setStackDepth(int depth) throws IllegalArgumentException, IllegalStateException;
Turn on stack trace for an event
Params:
  • eventTypeId – the event id
  • enabled – if stack traces should be enabled
/** * Turn on stack trace for an event * * @param eventTypeId the event id * * @param enabled if stack traces should be enabled */
public native void setStackTraceEnabled(long eventTypeId, boolean enabled);
Set thread buffer size.
Params:
  • size –
Throws:
/** * Set thread buffer size. * * @param size * * @throws IllegalArgumentException if size is not within a valid range * @throws IllegalStateException if size can't be changed */
public native void setThreadBufferSize(long size) throws IllegalArgumentException, IllegalStateException;
Set threshold for event, Long.MAXIMUM_VALUE = no limit
Params:
  • eventTypeId – the id of the event type
  • ticks – threshold in ticks,
Returns:true, if it could be set
/** * Set threshold for event, * * Long.MAXIMUM_VALUE = no limit * * @param eventTypeId the id of the event type * @param ticks threshold in ticks, * @return true, if it could be set */
public native boolean setThreshold(long eventTypeId, long ticks);
Store the metadata descriptor that is to be written at the end of a chunk, data should be written after GMT offset and size of metadata event should be adjusted Requires that JFR has been started with createNativeJFR()
Params:
  • bytes – binary representation of metadata descriptor
  • binary – representation of descriptor
/** * Store the metadata descriptor that is to be written at the end of a * chunk, data should be written after GMT offset and size of metadata event * should be adjusted * * Requires that JFR has been started with {@link #createNativeJFR()} * * @param bytes binary representation of metadata descriptor * * @param binary representation of descriptor */
public native void storeMetadataDescriptor(byte[] bytes); public void endRecording_() { endRecording(); recording = false; } public void beginRecording_() { beginRecording(); recording = true; } public boolean isRecording() { return recording; }
If the JVM supports JVM TI and retransformation has not been disabled this method will return true. This flag can not change during the lifetime of the JVM.
Returns:if transform is allowed
/** * If the JVM supports JVM TI and retransformation has not been disabled this * method will return true. This flag can not change during the lifetime of * the JVM. * * @return if transform is allowed */
public native boolean getAllowedToDoEventRetransforms();
Set up native resources, data structures, threads etc. for JFR
Params:
  • simulateFailure – simulate a initialization failure and rollback in native, used for testing purposes
Throws:
/** * Set up native resources, data structures, threads etc. for JFR * * @param simulateFailure simulate a initialization failure and rollback in * native, used for testing purposes * * @throws IllegalStateException if native part of JFR could not be created. * */
private native boolean createJFR(boolean simulateFailure) throws IllegalStateException;
Destroys native part of JFR. If already destroy, call is ignored. Requires that JFR has been started with createNativeJFR()
Returns:if an instance was actually destroyed.
/** * Destroys native part of JFR. If already destroy, call is ignored. * * Requires that JFR has been started with {@link #createNativeJFR()} * * @return if an instance was actually destroyed. * */
private native boolean destroyJFR(); public boolean createFailedNativeJFR() throws IllegalStateException { return createJFR(true); } public void createNativeJFR() { nativeOK = createJFR(false); } public boolean destroyNativeJFR() { boolean result = destroyJFR(); nativeOK = !result; return result; } public boolean hasNativeJFR() { return nativeOK; }
Cheap test to check if JFR functionality is available.
Returns:
/** * Cheap test to check if JFR functionality is available. * * @return */
public native boolean isAvailable();
To convert ticks to wall clock time.
/** * To convert ticks to wall clock time. */
public native double getTimeConversionFactor();
Return a unique identifier for a class. Compared to getClassId() , this method does not tag the class as being "in-use".
Params:
  • clazz – class
Returns:a unique class identifier
/** * Return a unique identifier for a class. Compared to {@link #getClassId()} * , this method does not tag the class as being "in-use". * * @param clazz class * * @return a unique class identifier */
public native long getTypeId(Class<?> clazz);
Fast path fetching the EventWriter using VM intrinsics
Returns:thread local EventWriter
/** * Fast path fetching the EventWriter using VM intrinsics * * @return thread local EventWriter */
@HotSpotIntrinsicCandidate public static native Object getEventWriter();
Create a new EventWriter
Returns:thread local EventWriter
/** * Create a new EventWriter * * @return thread local EventWriter */
public static native EventWriter newEventWriter();
Flushes the EventWriter for this thread.
/** * Flushes the EventWriter for this thread. */
public static native boolean flush(EventWriter writer, int uncommittedSize, int requestedSize);
Sets the location of the disk repository, to be used at an emergency dump.
Params:
  • dirText –
/** * Sets the location of the disk repository, to be used at an emergency * dump. * * @param dirText */
public native void setRepositoryLocation(String dirText);
Access to VM termination support.
Params:
  • errorMsg – descriptive message to be include in VM termination sequence
/** * Access to VM termination support. * *@param errorMsg descriptive message to be include in VM termination sequence */
public native void abort(String errorMsg);
Adds a string to the string constant pool. If the same string is added twice, two entries will be created.
Params:
  • id – identifier associated with the string, not negative
  • s – string constant to be added, not null
Returns:the current epoch of this insertion attempt
/** * Adds a string to the string constant pool. * * If the same string is added twice, two entries will be created. * * @param id identifier associated with the string, not negative * * @param s string constant to be added, not null * * @return the current epoch of this insertion attempt */
public static native boolean addStringConstant(boolean epoch, long id, String s);
Gets the address of the jboolean epoch. The epoch alternates every checkpoint.
Returns:The address of the jboolean.
/** * Gets the address of the jboolean epoch. * * The epoch alternates every checkpoint. * * @return The address of the jboolean. */
public native long getEpochAddress(); public native void uncaughtException(Thread thread, Throwable t);
Sets cutoff for event. Determines how long the event should be allowed to run. Long.MAXIMUM_VALUE = no limit
Params:
  • eventTypeId – the id of the event type
  • cutoffTicks – cutoff in ticks,
Returns:true, if it could be set
/** * Sets cutoff for event. * * Determines how long the event should be allowed to run. * * Long.MAXIMUM_VALUE = no limit * * @param eventTypeId the id of the event type * @param cutoffTicks cutoff in ticks, * @return true, if it could be set */
public native boolean setCutoff(long eventTypeId, long cutoffTicks);
Emit old object sample events.
Params:
  • cutoff – the cutoff in ticks
  • emitAll – emit all samples in old object queue
/** * Emit old object sample events. * * @param cutoff the cutoff in ticks * @param emitAll emit all samples in old object queue */
public native void emitOldObjectSamples(long cutoff, boolean emitAll);
Test if a chunk rotation is warranted.
Returns:if it is time to perform a chunk rotation
/** * Test if a chunk rotation is warranted. * * @return if it is time to perform a chunk rotation */
public native boolean shouldRotateDisk(); }