/* |
|
* 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.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(); |
|
// XXX |
|
// for (LogTag tag : LogTag.values()) { |
|
// subscribeLogLevel(tag, tag.id); |
|
// } |
|
Options.ensureInitialized(); |
|
EventHandlerProxyCreator.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 Event} |
|
* |
|
* @return list of event classes. |
|
*/ |
|
public native List<Class<? extends 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); |
|
/** |
|
* 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(); |
|
} |