1 /* 2 * Copyright (c) 2017, 2018, 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.io.IOException; 29 import java.util.List; 30 31 import jdk.jfr.Event; 32 33 /** 34 * Interface against the JVM. 35 * 36 */ 37 public final class JVM { 38 private static final JVM jvm = new JVM(); 39 40 // JVM signals file changes by doing Object#notifu on this object 41 static final Object FILE_DELTA_CHANGE = new Object(); 42 43 static final long RESERVED_CLASS_ID_LIMIT = 400; 44 45 private volatile boolean recording; 46 private volatile boolean nativeOK; 47 48 private static native void registerNatives(); 49 50 static { 51 registerNatives(); 52 // XXX 53 // for (LogTag tag : LogTag.values()) { 54 // subscribeLogLevel(tag, tag.id); 55 // } 56 Options.ensureInitialized(); 57 EventHandlerProxyCreator.ensureInitialized(); 58 } 59 60 /** 61 * Get the one and only JVM. 62 * 63 * @return the JVM 64 */ 65 public static JVM getJVM() { 66 return jvm; 67 } 68 69 private JVM() { 70 } 71 72 /** 73 * Begin recording events 74 * 75 * Requires that JFR has been started with {@link #createNativeJFR()} 76 */ 77 public native void beginRecording(); 78 79 /** 80 * Return ticks 81 * 82 * @return the time, in ticks 83 * 84 */ 85 // @HotSpotIntrinsicCandidate 86 public static native long counterTime(); 87 88 89 /** 90 * Emits native periodic event. 91 * 92 * @param eventTypeId type id 93 * 94 * @param timestamp commit time for event 95 * @param when when it is being done {@link Periodic.When} 96 * 97 * @return true if the event was committed 98 */ 99 public native boolean emitEvent(long eventTypeId, long timestamp, long when); 100 101 /** 102 * End recording events, which includes flushing data in thread buffers 103 * 104 * Requires that JFR has been started with {@link #createNativeJFR()} 105 * 106 */ 107 public native void endRecording(); 108 109 /** 110 * Return a list of all classes deriving from {@link Event} 111 * 112 * @return list of event classes. 113 */ 114 public native List<Class<? extends Event>> getAllEventClasses(); 115 116 /** 117 * Return a count of the number of unloaded classes deriving from {@link Event} 118 * 119 * @return number of unloaded event classes. 120 */ 121 public native long getUnloadedEventClassCount(); 122 123 /** 124 * Return a unique identifier for a class. The class is marked as being 125 * "in use" in JFR. 126 * 127 * @param clazz clazz 128 * 129 * @return a unique class identifier 130 */ 131 // @HotSpotIntrinsicCandidate 132 public static native long getClassId(Class<?> clazz); 133 134 // temporary workaround until we solve intrinsics supporting epoch shift tagging 135 public static native long getClassIdNonIntrinsic(Class<?> clazz); 136 137 /** 138 * Return process identifier. 139 * 140 * @return process identifier 141 */ 142 public native String getPid(); 143 144 /** 145 * Return unique identifier for stack trace. 146 * 147 * Requires that JFR has been started with {@link #createNativeJFR()} 148 * 149 * @param skipCount number of frames to skip 150 * @return a unique stack trace identifier 151 */ 152 public native long getStackTraceId(int skipCount); 153 154 /** 155 * Return identifier for thread 156 * 157 * @param t thread 158 * @return a unique thread identifier 159 */ 160 public native long getThreadId(Thread t); 161 162 /** 163 * Frequency, ticks per second 164 * 165 * @return frequency 166 */ 167 public native long getTicksFrequency(); 168 169 /** 170 * Write message to log. Should swallow null or empty message, and be able 171 * to handle any Java character and not crash with very large message 172 * 173 * @param tagSetId the tagset id 174 * @param level on level 175 * @param message log message 176 * 177 */ 178 public static native void log(int tagSetId, int level, String message); 179 180 /** 181 * Subscribe to LogLevel updates for LogTag 182 * 183 * @param lt the log tag to subscribe 184 * @param tagSetId the tagset id 185 */ 186 public static native void subscribeLogLevel(LogTag lt, int tagSetId); 187 188 /** 189 * Call to invoke event tagging and retransformation of the passed classes 190 * 191 * @param classes 192 */ 193 public native synchronized void retransformClasses(Class<?>[] classes); 194 195 /** 196 * Enable event 197 * 198 * @param eventTypeId event type id 199 * 200 * @param enabled enable event 201 */ 202 public native void setEnabled(long eventTypeId, boolean enabled); 203 204 /** 205 * Interval at which the JVM should notify on {@link #FILE_DELTA_CHANGE} 206 * 207 * @param delta number of bytes, reset after file rotation 208 */ 209 public native void setFileNotification(long delta); 210 211 /** 212 * Set the number of global buffers to use 213 * 214 * @param count 215 * 216 * @throws IllegalArgumentException if count is not within a valid range 217 * @throws IllegalStateException if value can't be changed 218 */ 219 public native void setGlobalBufferCount(long count) throws IllegalArgumentException, IllegalStateException; 220 221 /** 222 * Set size of a global buffer 223 * 224 * @param size 225 * 226 * @throws IllegalArgumentException if buffer size is not within a valid 227 * range 228 */ 229 public native void setGlobalBufferSize(long size) throws IllegalArgumentException; 230 231 /** 232 * Set overall memory size 233 * 234 * @param size 235 * 236 * @throws IllegalArgumentException if memory size is not within a valid 237 * range 238 */ 239 public native void setMemorySize(long size) throws IllegalArgumentException; 240 241 /** 242 243 /** 244 * Set interval for method samples, in milliseconds. 245 * 246 * Setting interval to 0 turns off the method sampler. 247 * 248 * @param intervalMillis the sampling interval 249 */ 250 public native void setMethodSamplingInterval(long type, long intervalMillis); 251 252 /** 253 * Sets the file where data should be written. 254 * 255 * Requires that JFR has been started with {@link #createNativeJFR()} 256 * 257 * <pre> 258 * Recording Previous Current Action 259 * ============================================== 260 * true null null Ignore, keep recording in-memory 261 * true null file1 Start disk recording 262 * true file null Copy out metadata to disk and continue in-memory recording 263 * true file1 file2 Copy out metadata and start with new File (file2) 264 * false * null Ignore, but start recording to memory with {@link #beginRecording()} 265 * false * file Ignore, but start recording to disk with {@link #beginRecording()} 266 * 267 * </pre> 268 * 269 * recording can be set to true/false with {@link #beginRecording()} 270 * {@link #endRecording()} 271 * 272 * @param file the file where data should be written, or null if it should 273 * not be copied out (in memory). 274 * 275 * @throws IOException 276 */ 277 public native void setOutput(String file); 278 279 /** 280 * Controls if a class deriving from jdk.jfr.Event should 281 * always be instrumented on class load. 282 * 283 * @param force, true to force initialization, false otherwise 284 */ 285 public native void setForceInstrumentation(boolean force); 286 287 /** 288 * Turn on/off thread sampling. 289 * 290 * @param sampleThreads true if threads should be sampled, false otherwise. 291 * 292 * @throws IllegalStateException if state can't be changed. 293 */ 294 public native void setSampleThreads(boolean sampleThreads) throws IllegalStateException; 295 296 /** 297 * Turn on/off compressed integers. 298 * 299 * @param compressed true if compressed integers should be used, false 300 * otherwise. 301 * 302 * @throws IllegalStateException if state can't be changed. 303 */ 304 public native void setCompressedIntegers(boolean compressed) throws IllegalStateException; 305 306 /** 307 * Set stack depth. 308 * 309 * @param depth 310 * 311 * @throws IllegalArgumentException if not within a valid range 312 * @throws IllegalStateException if depth can't be changed 313 */ 314 public native void setStackDepth(int depth) throws IllegalArgumentException, IllegalStateException; 315 316 /** 317 * Turn on stack trace for an event 318 * 319 * @param eventTypeId the event id 320 * 321 * @param enabled if stack traces should be enabled 322 */ 323 public native void setStackTraceEnabled(long eventTypeId, boolean enabled); 324 325 /** 326 * Set thread buffer size. 327 * 328 * @param size 329 * 330 * @throws IllegalArgumentException if size is not within a valid range 331 * @throws IllegalStateException if size can't be changed 332 */ 333 public native void setThreadBufferSize(long size) throws IllegalArgumentException, IllegalStateException; 334 335 /** 336 * Set threshold for event, 337 * 338 * Long.MAXIMUM_VALUE = no limit 339 * 340 * @param eventTypeId the id of the event type 341 * @param ticks threshold in ticks, 342 * @return true, if it could be set 343 */ 344 public native boolean setThreshold(long eventTypeId, long ticks); 345 346 /** 347 * Store the metadata descriptor that is to be written at the end of a 348 * chunk, data should be written after GMT offset and size of metadata event 349 * should be adjusted 350 * 351 * Requires that JFR has been started with {@link #createNativeJFR()} 352 * 353 * @param bytes binary representation of metadata descriptor 354 * 355 * @param binary representation of descriptor 356 */ 357 public native void storeMetadataDescriptor(byte[] bytes); 358 359 public void endRecording_() { 360 endRecording(); 361 recording = false; 362 } 363 364 public void beginRecording_() { 365 beginRecording(); 366 recording = true; 367 } 368 369 public boolean isRecording() { 370 return recording; 371 } 372 373 /** 374 * If the JVM supports JVM TI and retransformation has not been disabled this 375 * method will return true. This flag can not change during the lifetime of 376 * the JVM. 377 * 378 * @return if transform is allowed 379 */ 380 public native boolean getAllowedToDoEventRetransforms(); 381 382 /** 383 * Set up native resources, data structures, threads etc. for JFR 384 * 385 * @param simulateFailure simulate a initialization failure and rollback in 386 * native, used for testing purposes 387 * 388 * @throws IllegalStateException if native part of JFR could not be created. 389 * 390 */ 391 private native boolean createJFR(boolean simulateFailure) throws IllegalStateException; 392 393 /** 394 * Destroys native part of JFR. If already destroy, call is ignored. 395 * 396 * Requires that JFR has been started with {@link #createNativeJFR()} 397 * 398 * @return if an instance was actually destroyed. 399 * 400 */ 401 private native boolean destroyJFR(); 402 403 public boolean createFailedNativeJFR() throws IllegalStateException { 404 return createJFR(true); 405 } 406 407 public void createNativeJFR() { 408 nativeOK = createJFR(false); 409 } 410 411 public boolean destroyNativeJFR() { 412 boolean result = destroyJFR(); 413 nativeOK = !result; 414 return result; 415 } 416 417 public boolean hasNativeJFR() { 418 return nativeOK; 419 } 420 421 /** 422 * Cheap test to check if JFR functionality is available. 423 * 424 * @return 425 */ 426 public native boolean isAvailable(); 427 428 /** 429 * To convert ticks to wall clock time. 430 */ 431 public native double getTimeConversionFactor(); 432 433 /** 434 * Return a unique identifier for a class. Compared to {@link #getClassId()} 435 * , this method does not tag the class as being "in-use". 436 * 437 * @param clazz class 438 * 439 * @return a unique class identifier 440 */ 441 public native long getTypeId(Class<?> clazz); 442 443 /** 444 * Fast path fetching the EventWriter using VM intrinsics 445 * 446 * @return thread local EventWriter 447 */ 448 // @HotSpotIntrinsicCandidate 449 public static native Object getEventWriter(); 450 451 /** 452 * Create a new EventWriter 453 * 454 * @return thread local EventWriter 455 */ 456 public static native EventWriter newEventWriter(); 457 458 /** 459 * Flushes the EventWriter for this thread. 460 */ 461 public static native boolean flush(EventWriter writer, int uncommittedSize, int requestedSize); 462 463 /** 464 * Sets the location of the disk repository, to be used at an emergency 465 * dump. 466 * 467 * @param dirText 468 */ 469 public native void setRepositoryLocation(String dirText); 470 471 /** 472 * Access to VM termination support. 473 * 474 *@param errorMsg descriptive message to be include in VM termination sequence 475 */ 476 public native void abort(String errorMsg); 477 478 /** 479 * Adds a string to the string constant pool. 480 * 481 * If the same string is added twice, two entries will be created. 482 * 483 * @param id identifier associated with the string, not negative 484 * 485 * @param s string constant to be added, not null 486 * 487 * @return the current epoch of this insertion attempt 488 */ 489 public static native boolean addStringConstant(boolean epoch, long id, String s); 490 /** 491 * Gets the address of the jboolean epoch. 492 * 493 * The epoch alternates every checkpoint. 494 * 495 * @return The address of the jboolean. 496 */ 497 public native long getEpochAddress(); 498 499 public native void uncaughtException(Thread thread, Throwable t); 500 /** 501 * Sets cutoff for event. 502 * 503 * Determines how long the event should be allowed to run. 504 * 505 * Long.MAXIMUM_VALUE = no limit 506 * 507 * @param eventTypeId the id of the event type 508 * @param cutoffTicks cutoff in ticks, 509 * @return true, if it could be set 510 */ 511 public native boolean setCutoff(long eventTypeId, long cutoffTicks); 512 513 /** 514 * Emit old object sample events. 515 * 516 * @param cutoff the cutoff in ticks 517 * @param emitAll emit all samples in old object queue 518 */ 519 public native void emitOldObjectSamples(long cutoff, boolean emitAll); 520 521 /** 522 * Test if a chunk rotation is warranted. 523 * 524 * @return if it is time to perform a chunk rotation 525 */ 526 public native boolean shouldRotateDisk(); 527 }