1 /* 2 * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package jdk.jfr.internal; 27 28 import java.util.List; 29 30 import jdk.internal.HotSpotIntrinsicCandidate; 31 import jdk.jfr.Event; 32 import jdk.jfr.internal.handlers.EventHandler; 33 34 /** 35 * Interface against the JVM. 36 * 37 */ 38 public final class JVM { 39 private static final JVM jvm = new JVM(); 40 41 // JVM signals file changes by doing Object#notify on this object 42 static final Object FILE_DELTA_CHANGE = new Object(); 43 44 static final long RESERVED_CLASS_ID_LIMIT = 500; 45 46 private volatile boolean nativeOK; 47 registerNatives()48 private static native void registerNatives(); 49 50 static { registerNatives()51 registerNatives(); 52 for (LogTag tag : LogTag.values()) { subscribeLogLevel(tag, tag.id)53 subscribeLogLevel(tag, tag.id); 54 } Options.ensureInitialized()55 Options.ensureInitialized(); 56 } 57 58 /** 59 * Get the one and only JVM. 60 * 61 * @return the JVM 62 */ getJVM()63 public static JVM getJVM() { 64 return jvm; 65 } 66 JVM()67 private JVM() { 68 } 69 70 /** 71 * Marks current chunk as final 72 * <p> 73 * This allows streaming clients to read the chunk header and 74 * close the stream when no more data will be written into 75 * the current repository. 76 */ markChunkFinal()77 public native void markChunkFinal(); 78 79 /** 80 * Begin recording events 81 * 82 * Requires that JFR has been started with {@link #createNativeJFR()} 83 */ beginRecording()84 public native void beginRecording(); 85 86 /** 87 * Return true if the JVM is recording 88 */ isRecording()89 public native boolean isRecording(); 90 91 /** 92 * End recording events, which includes flushing data in thread buffers 93 * 94 * Requires that JFR has been started with {@link #createNativeJFR()} 95 * 96 */ endRecording()97 public native void endRecording(); 98 99 /** 100 * Return ticks 101 * 102 * @return the time, in ticks 103 * 104 */ 105 @HotSpotIntrinsicCandidate counterTime()106 public static native long counterTime(); 107 108 /** 109 * Emits native periodic event. 110 * 111 * @param eventTypeId type id 112 * 113 * @param timestamp commit time for event 114 * @param when when it is being done {@link Periodic.When} 115 * 116 * @return true if the event was committed 117 */ emitEvent(long eventTypeId, long timestamp, long when)118 public native boolean emitEvent(long eventTypeId, long timestamp, long when); 119 120 /** 121 * Return a list of all classes deriving from {@link jdk.internal.event.Event} 122 * 123 * @return list of event classes. 124 */ getAllEventClasses()125 public native List<Class<? extends jdk.internal.event.Event>> getAllEventClasses(); 126 127 /** 128 * Return a count of the number of unloaded classes deriving from {@link Event} 129 * 130 * @return number of unloaded event classes. 131 */ getUnloadedEventClassCount()132 public native long getUnloadedEventClassCount(); 133 134 /** 135 * Return a unique identifier for a class. The class is marked as being 136 * "in use" in JFR. 137 * 138 * @param clazz clazz 139 * 140 * @return a unique class identifier 141 */ 142 @HotSpotIntrinsicCandidate getClassId(Class<?> clazz)143 public static native long getClassId(Class<?> clazz); 144 145 // temporary workaround until we solve intrinsics supporting epoch shift tagging getClassIdNonIntrinsic(Class<?> clazz)146 public static native long getClassIdNonIntrinsic(Class<?> clazz); 147 148 /** 149 * Return process identifier. 150 * 151 * @return process identifier 152 */ getPid()153 public native String getPid(); 154 155 /** 156 * Return unique identifier for stack trace. 157 * 158 * Requires that JFR has been started with {@link #createNativeJFR()} 159 * 160 * @param skipCount number of frames to skip 161 * @return a unique stack trace identifier 162 */ getStackTraceId(int skipCount)163 public native long getStackTraceId(int skipCount); 164 165 /** 166 * Return identifier for thread 167 * 168 * @param t thread 169 * @return a unique thread identifier 170 */ getThreadId(Thread t)171 public native long getThreadId(Thread t); 172 173 /** 174 * Frequency, ticks per second 175 * 176 * @return frequency 177 */ getTicksFrequency()178 public native long getTicksFrequency(); 179 180 /** 181 * Write message to log. Should swallow null or empty message, and be able 182 * to handle any Java character and not crash with very large message 183 * 184 * @param tagSetId the tagset id 185 * @param level on level 186 * @param message log message 187 * 188 */ log(int tagSetId, int level, String message)189 public static native void log(int tagSetId, int level, String message); 190 191 /** 192 * Subscribe to LogLevel updates for LogTag 193 * 194 * @param lt the log tag to subscribe 195 * @param tagSetId the tagset id 196 */ subscribeLogLevel(LogTag lt, int tagSetId)197 public static native void subscribeLogLevel(LogTag lt, int tagSetId); 198 199 /** 200 * Call to invoke event tagging and retransformation of the passed classes 201 * 202 * @param classes 203 * 204 * @throws IllegalStateException if wrong JVMTI phase. 205 */ retransformClasses(Class<?>[] classes)206 public native synchronized void retransformClasses(Class<?>[] classes); 207 208 /** 209 * Enable event 210 * 211 * @param eventTypeId event type id 212 * 213 * @param enabled enable event 214 */ setEnabled(long eventTypeId, boolean enabled)215 public native void setEnabled(long eventTypeId, boolean enabled); 216 217 /** 218 * Interval at which the JVM should notify on {@link #FILE_DELTA_CHANGE} 219 * 220 * @param delta number of bytes, reset after file rotation 221 */ setFileNotification(long delta)222 public native void setFileNotification(long delta); 223 224 /** 225 * Set the number of global buffers to use 226 * 227 * @param count 228 * 229 * @throws IllegalArgumentException if count is not within a valid range 230 * @throws IllegalStateException if value can't be changed 231 */ setGlobalBufferCount(long count)232 public native void setGlobalBufferCount(long count) throws IllegalArgumentException, IllegalStateException; 233 234 /** 235 * Set size of a global buffer 236 * 237 * @param size 238 * 239 * @throws IllegalArgumentException if buffer size is not within a valid 240 * range 241 */ setGlobalBufferSize(long size)242 public native void setGlobalBufferSize(long size) throws IllegalArgumentException; 243 244 /** 245 * Set overall memory size 246 * 247 * @param size 248 * 249 * @throws IllegalArgumentException if memory size is not within a valid 250 * range 251 */ setMemorySize(long size)252 public native void setMemorySize(long size) throws IllegalArgumentException; 253 254 /** 255 * Set interval for method samples, in milliseconds. 256 * 257 * Setting interval to 0 turns off the method sampler. 258 * 259 * @param intervalMillis the sampling interval 260 */ setMethodSamplingInterval(long type, long intervalMillis)261 public native void setMethodSamplingInterval(long type, long intervalMillis); 262 263 /** 264 * Sets the file where data should be written. 265 * 266 * Requires that JFR has been started with {@link #createNativeJFR()} 267 * 268 * <pre> 269 * Recording Previous Current Action 270 * ============================================== 271 * true null null Ignore, keep recording in-memory 272 * true null file1 Start disk recording 273 * true file null Copy out metadata to disk and continue in-memory recording 274 * true file1 file2 Copy out metadata and start with new File (file2) 275 * false * null Ignore, but start recording to memory with {@link #beginRecording()} 276 * false * file Ignore, but start recording to disk with {@link #beginRecording()} 277 * 278 * </pre> 279 * 280 * recording can be set to true/false with {@link #beginRecording()} 281 * {@link #endRecording()} 282 * 283 * @param file the file where data should be written, or null if it should 284 * not be copied out (in memory). 285 */ setOutput(String file)286 public native void setOutput(String file); 287 288 /** 289 * Controls if a class deriving from jdk.jfr.Event should 290 * always be instrumented on class load. 291 * 292 * @param force, true to force initialization, false otherwise 293 */ setForceInstrumentation(boolean force)294 public native void setForceInstrumentation(boolean force); 295 296 /** 297 * Turn on/off thread sampling. 298 * 299 * @param sampleThreads true if threads should be sampled, false otherwise. 300 * 301 * @throws IllegalStateException if state can't be changed. 302 */ setSampleThreads(boolean sampleThreads)303 public native void setSampleThreads(boolean sampleThreads) throws IllegalStateException; 304 305 /** 306 * Turn on/off compressed integers. 307 * 308 * @param compressed true if compressed integers should be used, false 309 * otherwise. 310 * 311 * @throws IllegalStateException if state can't be changed. 312 */ setCompressedIntegers(boolean compressed)313 public native void setCompressedIntegers(boolean compressed) throws IllegalStateException; 314 315 /** 316 * Set stack depth. 317 * 318 * @param depth 319 * 320 * @throws IllegalArgumentException if not within a valid range 321 * @throws IllegalStateException if depth can't be changed 322 */ setStackDepth(int depth)323 public native void setStackDepth(int depth) throws IllegalArgumentException, IllegalStateException; 324 325 /** 326 * Turn on stack trace for an event 327 * 328 * @param eventTypeId the event id 329 * 330 * @param enabled if stack traces should be enabled 331 */ setStackTraceEnabled(long eventTypeId, boolean enabled)332 public native void setStackTraceEnabled(long eventTypeId, boolean enabled); 333 334 /** 335 * Set thread buffer size. 336 * 337 * @param size 338 * 339 * @throws IllegalArgumentException if size is not within a valid range 340 * @throws IllegalStateException if size can't be changed 341 */ setThreadBufferSize(long size)342 public native void setThreadBufferSize(long size) throws IllegalArgumentException, IllegalStateException; 343 344 /** 345 * Set threshold for event, 346 * 347 * Long.MAXIMUM_VALUE = no limit 348 * 349 * @param eventTypeId the id of the event type 350 * @param ticks threshold in ticks, 351 * @return true, if it could be set 352 */ setThreshold(long eventTypeId, long ticks)353 public native boolean setThreshold(long eventTypeId, long ticks); 354 355 /** 356 * Store the metadata descriptor that is to be written at the end of a 357 * chunk, data should be written after GMT offset and size of metadata event 358 * should be adjusted 359 * 360 * Requires that JFR has been started with {@link #createNativeJFR()} 361 * 362 * @param bytes binary representation of metadata descriptor 363 */ storeMetadataDescriptor(byte[] bytes)364 public native void storeMetadataDescriptor(byte[] bytes); 365 366 /** 367 * If the JVM supports JVM TI and retransformation has not been disabled this 368 * method will return true. This flag can not change during the lifetime of 369 * the JVM. 370 * 371 * @return if transform is allowed 372 */ getAllowedToDoEventRetransforms()373 public native boolean getAllowedToDoEventRetransforms(); 374 375 /** 376 * Set up native resources, data structures, threads etc. for JFR 377 * 378 * @param simulateFailure simulate a initialization failure and rollback in 379 * native, used for testing purposes 380 * 381 * @throws IllegalStateException if native part of JFR could not be created. 382 * 383 */ createJFR(boolean simulateFailure)384 private native boolean createJFR(boolean simulateFailure) throws IllegalStateException; 385 386 /** 387 * Destroys native part of JFR. If already destroy, call is ignored. 388 * 389 * Requires that JFR has been started with {@link #createNativeJFR()} 390 * 391 * @return if an instance was actually destroyed. 392 * 393 */ destroyJFR()394 private native boolean destroyJFR(); 395 createFailedNativeJFR()396 public boolean createFailedNativeJFR() throws IllegalStateException { 397 return createJFR(true); 398 } 399 createNativeJFR()400 public void createNativeJFR() { 401 nativeOK = createJFR(false); 402 } 403 destroyNativeJFR()404 public boolean destroyNativeJFR() { 405 boolean result = destroyJFR(); 406 nativeOK = !result; 407 return result; 408 } 409 hasNativeJFR()410 public boolean hasNativeJFR() { 411 return nativeOK; 412 } 413 414 /** 415 * Cheap test to check if JFR functionality is available. 416 * 417 * @return 418 */ isAvailable()419 public native boolean isAvailable(); 420 421 /** 422 * To convert ticks to wall clock time. 423 */ getTimeConversionFactor()424 public native double getTimeConversionFactor(); 425 426 /** 427 * Return a unique identifier for a class. Compared to {@link #getClassId(Class)}, 428 * this method does not tag the class as being "in-use". 429 * 430 * @param clazz class 431 * 432 * @return a unique class identifier 433 */ getTypeId(Class<?> clazz)434 public native long getTypeId(Class<?> clazz); 435 436 /** 437 * Fast path fetching the EventWriter using VM intrinsics 438 * 439 * @return thread local EventWriter 440 */ 441 @HotSpotIntrinsicCandidate getEventWriter()442 public static native Object getEventWriter(); 443 444 /** 445 * Create a new EventWriter 446 * 447 * @return thread local EventWriter 448 */ newEventWriter()449 public static native EventWriter newEventWriter(); 450 451 /** 452 * Flushes the EventWriter for this thread. 453 */ flush(EventWriter writer, int uncommittedSize, int requestedSize)454 public static native boolean flush(EventWriter writer, int uncommittedSize, int requestedSize); 455 456 /** 457 * Flushes all thread buffers to disk and the constant pool data needed to read 458 * them. 459 * <p> 460 * When the method returns, the chunk header should be updated with valid 461 * pointers to the metadata event, last check point event, correct file size and 462 * the generation id. 463 * 464 */ flush()465 public native void flush(); 466 467 /** 468 * Sets the location of the disk repository, to be used at an emergency 469 * dump. 470 * 471 * @param dirText 472 */ setRepositoryLocation(String dirText)473 public native void setRepositoryLocation(String dirText); 474 475 /** 476 * Access to VM termination support. 477 * 478 * @param errorMsg descriptive message to be include in VM termination sequence 479 */ abort(String errorMsg)480 public native void abort(String errorMsg); 481 482 /** 483 * Adds a string to the string constant pool. 484 * 485 * If the same string is added twice, two entries will be created. 486 * 487 * @param id identifier associated with the string, not negative 488 * 489 * @param s string constant to be added, not null 490 * 491 * @return true, if the string was successfully added. 492 */ addStringConstant(long id, String s)493 public static native boolean addStringConstant(long id, String s); 494 uncaughtException(Thread thread, Throwable t)495 public native void uncaughtException(Thread thread, Throwable t); 496 497 /** 498 * Sets cutoff for event. 499 * 500 * Determines how long the event should be allowed to run. 501 * 502 * Long.MAXIMUM_VALUE = no limit 503 * 504 * @param eventTypeId the id of the event type 505 * @param cutoffTicks cutoff in ticks, 506 * @return true, if it could be set 507 */ setCutoff(long eventTypeId, long cutoffTicks)508 public native boolean setCutoff(long eventTypeId, long cutoffTicks); 509 510 /** 511 * Emit old object sample events. 512 * 513 * @param cutoff the cutoff in ticks 514 * @param emitAll emit all samples in old object queue 515 * @param skipBFS don't use BFS when searching for path to GC root 516 */ emitOldObjectSamples(long cutoff, boolean emitAll, boolean skipBFS)517 public native void emitOldObjectSamples(long cutoff, boolean emitAll, boolean skipBFS); 518 519 /** 520 * Test if a chunk rotation is warranted. 521 * 522 * @return if it is time to perform a chunk rotation 523 */ shouldRotateDisk()524 public native boolean shouldRotateDisk(); 525 526 /** 527 * Exclude a thread from the jfr system 528 * 529 */ exclude(Thread thread)530 public native void exclude(Thread thread); 531 532 /** 533 * Include a thread back into the jfr system 534 * 535 */ include(Thread thread)536 public native void include(Thread thread); 537 538 /** 539 * Test if a thread ius currently excluded from the jfr system. 540 * 541 * @return is thread currently excluded 542 */ isExcluded(Thread thread)543 public native boolean isExcluded(Thread thread); 544 545 /** 546 * Get the start time in nanos from the header of the current chunk 547 * 548 * @return start time of the recording in nanos, -1 in case of in-memory 549 */ getChunkStartNanos()550 public native long getChunkStartNanos(); 551 552 /** 553 * Stores an EventHandler to the eventHandler field of an event class. 554 * 555 * @param eventClass the class, not {@code null} 556 * 557 * @param handler the handler, may be {@code null} 558 * 559 * @return if the field could be set 560 */ setHandler(Class<? extends jdk.internal.event.Event> eventClass, EventHandler handler)561 public native boolean setHandler(Class<? extends jdk.internal.event.Event> eventClass, EventHandler handler); 562 563 /** 564 * Retrieves the EventHandler for an event class. 565 * 566 * @param eventClass the class, not {@code null} 567 * 568 * @return the handler, may be {@code null} 569 */ getHandler(Class<? extends jdk.internal.event.Event> eventClass)570 public native Object getHandler(Class<? extends jdk.internal.event.Event> eventClass); 571 572 /** 573 * Returns the id for the Java types defined in metadata.xml. 574 * 575 * @param name the name of the type 576 * 577 * @return the id, or a negative value if it does not exists. 578 */ getTypeId(String name)579 public native long getTypeId(String name); 580 } 581