What is the WhiteBox API

The WhiteBox API is a white-box testing tool that comes with HotSpot VM, exposing the internal apis of many core mechanisms for white-box testing of the JVM, embodying JVM features, and learning to understand and tune JVM parameters. The WhiteBox API was introduced in Java 7, and is currently available in Java 8 LTS and Java 11 LTS. Java 9 introduced modularity so the WhiteBox API has changed). This API is not compiled in the JDK by default, but its implementation is compiled in the JDK. So if you want to use this API, you need to compile the required API yourself, add Java’s BootClassPath and enable the WhiteBox API.

How is the WhiteBox API implemented

The WhiteBox API is a Java class that is included in the JDK’s test package and is not compiled into the JDK in standard distributions by default.

test/lib/sun/hotspot/WhiteBox.java

package sun.hotspot; Public class WhiteBox {// Force Young GC public native void youngGC(); // Force Full GC public native void fullGC(); }Copy the code

As you can see, all apis are JNI calls.

src/hotspot/share/prims/whitebox.cpp

WB_ENTRY(void, WB_FullGC(JNIEnv* env, jobject o)) Universe::heap()->soft_ref_policy()->set_should_clear_all_soft_refs(true); Universe::heap()->collect(GCCause::_wb_full_gc); #if INCLUDE_G1GC if (UseG1GC) { // Needs to be cleared explicitly for G1 Universe::heap()->soft_ref_policy()->set_should_clear_all_soft_refs(false); } #endif // INCLUDE_G1GC WB_END WB_ENTRY(void, WB_YoungGC(JNIEnv* env, jobject o)) Universe::heap()->collect(GCCause::_wb_young_gc); YoungGC WB_END {CC ", "CC" V "(), (void *) & WB_YoungGC}, {CC" fullGC, "CC" V "(), (void *) & WB_FullGC}, / / omit other codeCopy the code

As you can see, the JNI invocation implementation directly calls the relevant interfaces of the underlying JVM, exposing some of the JVM’s key mechanisms for white-box testing. However, as mentioned earlier, the JDK distribution does not include the test code under Test, which means that the JAR containing the WhiteBox API is not included in the default JDK. This requires us to compile the code ourselves.

What is the BootClassPath

There are three different class loaders in Java: Application Classloader, Extension Classloader, and root bootstrap classloader.

  • Apply the class loader and load all the class files in our classpath directory
  • Extension classloader, the class that loads the standard Java library extension, is all the classes in the /lib/ext directory of your JRE directory
  • Bootstrap classloader, a classloader that scans the standard Java libraries under BootClassPath. The standard Java class library restricts some classes to package paths that must be loaded through the root class loader.

For the WhiteBox API, because the package is Sun.hotspot, the normal classloader cannot load the classes in the package path, so it needs to be loaded through the root classloader.

How do I specify BootClassPath

In Java 8, this is specified by -xBootclasspath: or -xbootclasspath /p:, for example:

-Xbootclasspath:/home/project/whitebox.jar
-Xbootclasspath/p:/home/project/whitebox.jar
Copy the code

In versions after Java 9, these parameters are out of date and need to be changed to -xBootCLASSPath /a:, for example:

-Xbootclasspath/a:/home/project/whitebox.jar
Copy the code

-Xbootclasspath is no longer a supported option.

Corresponding to the JDK source code is here: SRC/hotspot/share/runtime/arguments. CPP

// -bootclasspath: } else if (match_option(option, "-Xbootclasspath:", &tail)) { jio_fprintf(defaultStream::output_stream(), "-Xbootclasspath is no longer a supported option.\n"); return JNI_EINVAL; // -bootclasspath/a: } else if (match_option(option, "-Xbootclasspath/a:", Arguments:: append_sysCLASspath (tail); // Add Arguments to bootclasspath. // -bootclasspath/p: } else if (match_option(option, "-Xbootclasspath/p:", &tail)) { jio_fprintf(defaultStream::output_stream(), "-Xbootclasspath/p is no longer a supported option.\n"); return JNI_EINVAL; }Copy the code

Use the WhiteBox API

1. Compile the WhiteBox API

Remove https://github.com/openjdk/jdk/tree/master/test/lib path under sun directory, compiled into a jar package, name is whitebox hypothesis. The jar

2. Write test programs

Add whitebox.jar to your project dependencies and write the code

public static void main(String[] args) throws Exception { WhiteBox whiteBox = WhiteBox.getWhiteBox(); Long ReservedCodeCacheSize = whiteBox. GetUintxVMFlag ("ReservedCodeCacheSize");  System.out.println(reservedCodeCacheSize); // printHeapSizes(); // Execute fullGC whitebox.fullgc (); Thread.currentthread ().join(); thread.currentThread ().join(); }Copy the code

3. Start the program to view the effect

Use the launch parameters – Xbootclasspath/a: / home/project/whitebox jar – XX: XX: + UnlockDiagnosticVMOptions – + WhiteBoxAPI Xlog: gc start the program. The first three flags indicate that the WhiteBox API is enabled, and the last Flag indicates that GC INFO level logs are printed to the console.

My output:

[0.025s][info][GC] Using G1 251658240 Minimum heap 8388608 Initial heap 268435456 Maximum heap 4276092928 Space Alignment 2097152 Heap alignment 2097152 [0.899s][INFO][GC] GC(0) Pause Full (WhiteBox Initiated Full GC) 5M->0M(20M) 45.183 msCopy the code

Usage scenarios for the WhiteBox API

  1. The WhiteBox API is used to test the JDK framework source code
  2. When the JVM is compacted, scenarios need to be simulated and low-level operations need to be performed using the WhiteBox API, such as forcing the Full GC. Jcstress famously uses the WhiteBox API to pressure the JVM
  3. Some performance limit scenarios need to use the WhiteAPI for simulation and pressure measurement
  4. It will be used when you learn the principles of the JVM.

Finally, in my series of columns exploring the JVM through JFR and logging, I will often use the WhiteBox API to simulate various JFR events to help you better understand the underlying principles of the JVM, performance bottlenecks, JVM tuning, and more. You are welcome to subscribe