JVM.java 15.4 KB
Newer Older
A
apetushkov 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
/*
 * 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();
57
        EventHandlerProxyCreator.ensureInitialized();
A
apetushkov 已提交
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295
    }

    /**
     * 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;

296 297 298 299 300 301 302 303 304 305 306 307 308 309
    /**
     * Turn on/off objects allocations sampling.
     *
     * @param sampleAllocations true if object allocations should be sampled, false otherwise.
     */
    public native void setSampleObjectAllocations(boolean sampleAllocations);

    /**
     * Set object allocations sampling interval.
     *
     * @param interval
     */
    public native void setObjectAllocationsSamplingInterval(long interval) throws IllegalArgumentException;

A
apetushkov 已提交
310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533
    /**
     * 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);
534 535 536 537 538 539 540

    /**
     * Test if a chunk rotation is warranted.
     *
     * @return if it is time to perform a chunk rotation
     */
    public native boolean shouldRotateDisk();
A
apetushkov 已提交
541
}