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