| /* |
| * Copyright (c) 2017, 2019, 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. |
| * |
| */ |
| 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. |
| * |
| * @return the JVM |
| */ |
| public static JVM getJVM() { |
| return jvm; |
| } |
| |
| private JVM() { |
| } |
| |
| /** |
| * Begin recording events |
| * |
| * Requires that JFR has been started with {@link #createNativeJFR()} |
| */ |
| public native void beginRecording(); |
| |
| /** |
| * Return ticks |
| * |
| * @return the time, in ticks |
| * |
| */ |
| @HotSpotIntrinsicCandidate |
| public static native long counterTime(); |
| |
| |
| /** |
| * 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 {@link #createNativeJFR()} |
| * |
| */ |
| public native void endRecording(); |
| |
| /** |
| * 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 {@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. |
| * |
| * @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. |
| * |
| * @return process identifier |
| */ |
| public native String getPid(); |
| |
| /** |
| * 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 |
| * |
| * @param t thread |
| * @return a unique thread identifier |
| */ |
| public native long getThreadId(Thread t); |
| |
| /** |
| * 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 |
| * |
| * @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 |
| * |
| * @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 |
| * |
| * @param classes |
| */ |
| public native synchronized void retransformClasses(Class<?>[] classes); |
| |
| /** |
| * 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 {@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 |
| * |
| * @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 |
| * |
| * @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 |
| * |
| * @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. |
| * |
| * @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 {@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. |
| * |
| * @param force, true to force initialization, false otherwise |
| */ |
| public native void setForceInstrumentation(boolean force); |
| |
| /** |
| * 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. |
| * |
| * @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. |
| * |
| * @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 |
| * |
| * @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. |
| * |
| * @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 |
| * |
| * @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 {@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. |
| * |
| * @return if transform is allowed |
| */ |
| public native boolean getAllowedToDoEventRetransforms(); |
| |
| /** |
| * 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 {@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. |
| * |
| * @return |
| */ |
| public native boolean isAvailable(); |
| |
| /** |
| * To convert ticks to wall clock time. |
| */ |
| public native double getTimeConversionFactor(); |
| |
| /** |
| * 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 |
| * |
| * @return thread local EventWriter |
| */ |
| @HotSpotIntrinsicCandidate |
| public static native Object getEventWriter(); |
| |
| /** |
| * Create a new EventWriter |
| * |
| * @return thread local EventWriter |
| */ |
| public static native EventWriter newEventWriter(); |
| |
| /** |
| * Flushes the EventWriter for this thread. |
| */ |
| public static native boolean flush(EventWriter writer, int uncommittedSize, int requestedSize); |
| |
| /** |
| * Flushes all thread buffers to disk and the constant pool data needed to read |
| * them. |
| * <p> |
| * When the method returns, the chunk header should be updated with valid |
| * pointers to the metadata event, last check point event, correct file size and |
| * the generation id. |
| * |
| */ |
| public native void flush(); |
| /** |
| * 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. |
| * |
| *@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. |
| * |
| * @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. |
| * |
| * @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 |
| * |
| * @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. |
| * |
| * @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. |
| * |
| * @return if it is time to perform a chunk rotation |
| */ |
| public native boolean shouldRotateDisk(); |
| |
| /** |
| * Exclude a thread from the jfr system |
| * |
| */ |
| public native void exclude(Thread thread); |
| |
| /** |
| * Include a thread back into the jfr system |
| * |
| */ |
| public native void include(Thread thread); |
| |
| /** |
| * Test if a thread ius currently excluded from the jfr system. |
| * |
| * @return is thread currently excluded |
| */ |
| public native boolean isExcluded(Thread thread); |
| |
| /** |
| * Get the start time in nanos from the header of the current chunk |
| * |
| *@return start time of the recording in nanos, -1 in case of in-memory |
| */ |
| public native long getChunkStartNanos(); |
| } |