1 /*
  2  * Copyright (c) 2012, 2023, 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.
  8  *
  9  * This code is distributed in the hope that it will be useful, but WITHOUT
 10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  * version 2 for more details (a copy is included in the LICENSE file that
 13  * accompanied this code).
 14  *
 15  * You should have received a copy of the GNU General Public License version
 16  * 2 along with this work; if not, write to the Free Software Foundation,
 17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18  *
 19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  * or visit www.oracle.com if you need additional information or have any
 21  * questions.
 22  */
 23 
 24 package jdk.test.whitebox;
 25 
 26 import java.lang.management.MemoryUsage;
 27 import java.lang.reflect.Executable;
 28 import java.util.Arrays;
 29 import java.util.List;
 30 import java.util.function.BiFunction;
 31 import java.util.function.Function;
 32 import java.security.BasicPermission;
 33 import java.util.Objects;
 34 
 35 import jdk.test.whitebox.parser.DiagnosticCommand;
 36 
 37 public class WhiteBox {
 38   @SuppressWarnings("serial")
 39   public static class WhiteBoxPermission extends BasicPermission {
 40     public WhiteBoxPermission(String s) {
 41       super(s);
 42     }
 43   }
 44 
 45   private WhiteBox() {}
 46   private static final WhiteBox instance = new WhiteBox();
 47   private static native void registerNatives();
 48 
 49   /**
 50    * Returns the singleton WhiteBox instance.
 51    *
 52    * The returned WhiteBox object should be carefully guarded
 53    * by the caller, since it can be used to read and write data
 54    * at arbitrary memory addresses. It must never be passed to
 55    * untrusted code.
 56    */
 57   public synchronized static WhiteBox getWhiteBox() {
 58     @SuppressWarnings("removal")
 59     SecurityManager sm = System.getSecurityManager();
 60     if (sm != null) {
 61       sm.checkPermission(new WhiteBoxPermission("getInstance"));
 62     }
 63     return instance;
 64   }
 65 
 66   static {
 67     registerNatives();
 68   }
 69 
 70   // Get the maximum heap size supporting COOPs
 71   public native long getCompressedOopsMaxHeapSize();
 72   // Arguments
 73   public native void printHeapSizes();
 74 
 75   // Memory
 76   private native long getObjectAddress0(Object o);
 77   public           long getObjectAddress(Object o) {
 78     Objects.requireNonNull(o);
 79     return getObjectAddress0(o);
 80   }
 81 
 82   public native int  getHeapOopSize();
 83   public native int  getVMPageSize();
 84   public native long getVMAllocationGranularity();
 85   public native long getVMLargePageSize();
 86   public native long getHeapSpaceAlignment();
 87   public native long getHeapAlignment();
 88 
 89   private native boolean isObjectInOldGen0(Object o);
 90   public         boolean isObjectInOldGen(Object o) {
 91     Objects.requireNonNull(o);
 92     return isObjectInOldGen0(o);
 93   }
 94 
 95   private native long getObjectSize0(Object o);
 96   public         long getObjectSize(Object o) {
 97     Objects.requireNonNull(o);
 98     return getObjectSize0(o);
 99   }
100 
101   // Runtime
102   // Make sure class name is in the correct format
103   public int countAliveClasses(String name) {
104     return countAliveClasses0(name.replace('.', '/'));
105   }
106   private native int countAliveClasses0(String name);
107 
108   public boolean isClassAlive(String name) {
109     return countAliveClasses(name) != 0;
110   }
111 
112   public  native int getSymbolRefcount(String name);
113 
114   public native boolean deflateIdleMonitors();
115 
116   private native boolean isMonitorInflated0(Object obj);
117   public         boolean isMonitorInflated(Object obj) {
118     Objects.requireNonNull(obj);
119     return isMonitorInflated0(obj);
120   }
121 
122   public native void forceSafepoint();
123 
124   public native void forceClassLoaderStatsSafepoint();
125 
126   private native long getConstantPool0(Class<?> aClass);
127   public         long getConstantPool(Class<?> aClass) {
128     Objects.requireNonNull(aClass);
129     return getConstantPool0(aClass);
130   }
131 
132   private native Object[] getResolvedReferences0(Class<?> aClass);
133   public         Object[] getResolvedReferences(Class<?> aClass) {
134     Objects.requireNonNull(aClass);
135     return getResolvedReferences0(aClass);
136   }
137 
138   private native int remapInstructionOperandFromCPCache0(Class<?> aClass, int index);
139   public         int remapInstructionOperandFromCPCache(Class<?> aClass, int index) {
140     Objects.requireNonNull(aClass);
141     return remapInstructionOperandFromCPCache0(aClass, index);
142   }
143 
144   private native int encodeConstantPoolIndyIndex0(int index);
145   public         int encodeConstantPoolIndyIndex(int index) {
146     return encodeConstantPoolIndyIndex0(index);
147   }
148 
149   private native Object[] getObjectsViaKlassOopMaps0(Object thing);
150   public Object[] getObjectsViaKlassOopMaps(Object thing) {
151     Objects.requireNonNull(thing);
152     return getObjectsViaKlassOopMaps0(thing);
153   }
154 
155   private native Object[] getObjectsViaOopIterator0(Object thing);
156   public Object[] getObjectsViaOopIterator(Object thing) {
157     Objects.requireNonNull(thing);
158     return getObjectsViaOopIterator0(thing);
159   }
160 
161   public native Object[] getObjectsViaFrameOopIterator(int depth);
162 
163   private native int getFieldEntriesLength0(Class<?> aClass);
164   public         int getFieldEntriesLength(Class<?> aClass) {
165     Objects.requireNonNull(aClass);
166     return getFieldEntriesLength0(aClass);
167   }
168 
169   private native int getFieldCPIndex0(Class<?> aClass, int index);
170   public         int getFieldCPIndex(Class<?> aClass, int index) {
171     Objects.requireNonNull(aClass);
172     return getFieldCPIndex0(aClass, index);
173   }
174 
175   private native int getMethodEntriesLength0(Class<?> aClass);
176   public         int getMethodEntriesLength(Class<?> aClass) {
177     Objects.requireNonNull(aClass);
178     return getMethodEntriesLength0(aClass);
179   }
180 
181   private native int getMethodCPIndex0(Class<?> aClass, int index);
182   public         int getMethodCPIndex(Class<?> aClass, int index) {
183     Objects.requireNonNull(aClass);
184     return getMethodCPIndex0(aClass, index);
185   }
186 
187   private native int getIndyInfoLength0(Class<?> aClass);
188   public         int getIndyInfoLength(Class<?> aClass) {
189     Objects.requireNonNull(aClass);
190     return getIndyInfoLength0(aClass);
191   }
192 
193   private native int getIndyCPIndex0(Class<?> aClass, int index);
194   public         int getIndyCPIndex(Class<?> aClass, int index) {
195     Objects.requireNonNull(aClass);
196     return getIndyCPIndex0(aClass, index);
197   }
198 
199   private native String printClasses0(String classNamePattern, int flags);
200   public         String printClasses(String classNamePattern, int flags) {
201     Objects.requireNonNull(classNamePattern);
202     return printClasses0(classNamePattern, flags);
203   }
204 
205   private native String printMethods0(String classNamePattern, String methodPattern, int flags);
206   public         String printMethods(String classNamePattern, String methodPattern, int flags) {
207     Objects.requireNonNull(classNamePattern);
208     Objects.requireNonNull(methodPattern);
209     return printMethods0(classNamePattern, methodPattern, flags);
210   }
211 
212   // JVMTI
213   private native void addToBootstrapClassLoaderSearch0(String segment);
214   public         void addToBootstrapClassLoaderSearch(String segment){
215     Objects.requireNonNull(segment);
216     addToBootstrapClassLoaderSearch0(segment);
217   }
218 
219   private native void addToSystemClassLoaderSearch0(String segment);
220   public         void addToSystemClassLoaderSearch(String segment) {
221     Objects.requireNonNull(segment);
222     addToSystemClassLoaderSearch0(segment);
223   }
224 
225   // G1
226 
227   public native boolean g1InConcurrentMark();
228   public native int g1CompletedConcurrentMarkCycles();
229 
230   // Perform a complete concurrent GC cycle, using concurrent GC breakpoints.
231   // Completes any in-progress cycle before performing the requested cycle.
232   // Returns true if the cycle completed successfully.  If the cycle was not
233   // successful (e.g. it was aborted), then throws RuntimeException if
234   // errorIfFail is true, returning false otherwise.
235   public boolean g1RunConcurrentGC(boolean errorIfFail) {
236     try {
237       // Take control, waiting until any in-progress cycle completes.
238       concurrentGCAcquireControl();
239       int count = g1CompletedConcurrentMarkCycles();
240       concurrentGCRunTo(AFTER_MARKING_STARTED, false);
241       concurrentGCRunToIdle();
242       if (count < g1CompletedConcurrentMarkCycles()) {
243         return true;
244       } else if (errorIfFail) {
245         throw new RuntimeException("Concurrent GC aborted");
246       } else {
247         return false;
248       }
249     } finally {
250       concurrentGCReleaseControl();
251     }
252   }
253 
254   public void g1RunConcurrentGC() {
255     g1RunConcurrentGC(true);
256   }
257 
258   // Start a concurrent GC cycle, using concurrent GC breakpoints.
259   // The concurrent GC will continue in parallel with the caller.
260   // Completes any in-progress cycle before starting the requested cycle.
261   public void g1StartConcurrentGC() {
262     try {
263       // Take control, waiting until any in-progress cycle completes.
264       concurrentGCAcquireControl();
265       concurrentGCRunTo(AFTER_MARKING_STARTED, false);
266     } finally {
267       // Release control, permitting the cycle to complete.
268       concurrentGCReleaseControl();
269     }
270   }
271 
272   public native boolean g1HasRegionsToUncommit();
273   private native boolean g1IsHumongous0(Object o);
274   public         boolean g1IsHumongous(Object o) {
275     Objects.requireNonNull(o);
276     return g1IsHumongous0(o);
277   }
278 
279   private native boolean g1BelongsToHumongousRegion0(long adr);
280   public         boolean g1BelongsToHumongousRegion(long adr) {
281     if (adr == 0) {
282       throw new IllegalArgumentException("adr argument should not be null");
283     }
284     return g1BelongsToHumongousRegion0(adr);
285   }
286 
287 
288   private native boolean g1BelongsToFreeRegion0(long adr);
289   public         boolean g1BelongsToFreeRegion(long adr) {
290     if (adr == 0) {
291       throw new IllegalArgumentException("adr argument should not be null");
292     }
293     return g1BelongsToFreeRegion0(adr);
294   }
295 
296   public native long    g1NumMaxRegions();
297   public native long    g1NumFreeRegions();
298   public native int     g1RegionSize();
299   public native MemoryUsage g1AuxiliaryMemoryUsage();
300   private  native Object[]    parseCommandLine0(String commandline, char delim, DiagnosticCommand[] args);
301   public          Object[]    parseCommandLine(String commandline, char delim, DiagnosticCommand[] args) {
302     Objects.requireNonNull(args);
303     return parseCommandLine0(commandline, delim, args);
304   }
305 
306   public native int g1ActiveMemoryNodeCount();
307   public native int[] g1MemoryNodeIds();
308 
309   // Parallel GC
310   public native long psVirtualSpaceAlignment();
311   public native long psHeapGenerationAlignment();
312 
313   /**
314    * Enumerates old regions with liveness less than specified and produces some statistics
315    * @param liveness percent of region's liveness (live_objects / total_region_size * 100).
316    * @return long[3] array where long[0] - total count of old regions
317    *                             long[1] - total memory of old regions
318    *                             long[2] - lowest estimation of total memory of old regions to be freed (non-full
319    *                             regions are not included)
320    */
321   public native long[] g1GetMixedGCInfo(int liveness);
322 
323   // NMT
324   public native long NMTMalloc(long size);
325   public native void NMTFree(long mem);
326   public native long NMTReserveMemory(long size);
327   public native long NMTAttemptReserveMemoryAt(long addr, long size);
328   public native void NMTCommitMemory(long addr, long size);
329   public native void NMTUncommitMemory(long addr, long size);
330   public native void NMTReleaseMemory(long addr, long size);
331   public native long NMTMallocWithPseudoStack(long size, int index);
332   public native long NMTMallocWithPseudoStackAndType(long size, int index, int type);
333   public native int NMTGetHashSize();
334   public native long NMTNewArena(long initSize);
335   public native void NMTFreeArena(long arena);
336   public native void NMTArenaMalloc(long arena, long size);
337 
338   // Compiler
339 
340   // Determines if the libgraal shared library file is present.
341   public native boolean hasLibgraal();
342   public native boolean isC2OrJVMCIIncluded();
343   public native boolean isJVMCISupportedByGC();
344 
345   public native int     matchesMethod(Executable method, String pattern);
346   public native int     matchesInline(Executable method, String pattern);
347   public native boolean shouldPrintAssembly(Executable method, int comp_level);
348   public native int     deoptimizeFrames(boolean makeNotEntrant);
349   public native boolean isFrameDeoptimized(int depth);
350   public native void    deoptimizeAll();
351 
352   public        boolean isMethodCompiled(Executable method) {
353     return isMethodCompiled(method, false /*not osr*/);
354   }
355   private native boolean isMethodCompiled0(Executable method, boolean isOsr);
356   public         boolean isMethodCompiled(Executable method, boolean isOsr){
357     Objects.requireNonNull(method);
358     return isMethodCompiled0(method, isOsr);
359   }
360   public        boolean isMethodCompilable(Executable method) {
361     return isMethodCompilable(method, -1 /*any*/);
362   }
363   public        boolean isMethodCompilable(Executable method, int compLevel) {
364     return isMethodCompilable(method, compLevel, false /*not osr*/);
365   }
366   private native boolean isMethodCompilable0(Executable method, int compLevel, boolean isOsr);
367   public         boolean isMethodCompilable(Executable method, int compLevel, boolean isOsr) {
368     Objects.requireNonNull(method);
369     return isMethodCompilable0(method, compLevel, isOsr);
370   }
371   private native boolean isMethodQueuedForCompilation0(Executable method);
372   public         boolean isMethodQueuedForCompilation(Executable method) {
373     Objects.requireNonNull(method);
374     return isMethodQueuedForCompilation0(method);
375   }
376   // Determine if the compiler corresponding to the compilation level 'compLevel'
377   // and to the compilation context 'compilation_context' provides an intrinsic
378   // for the method 'method'. An intrinsic is available for method 'method' if:
379   //  - the intrinsic is enabled (by using the appropriate command-line flag) and
380   //  - the platform on which the VM is running provides the instructions necessary
381   //    for the compiler to generate the intrinsic code.
382   //
383   // The compilation context is related to using the DisableIntrinsic flag on a
384   // per-method level, see hotspot/src/share/vm/compiler/abstractCompiler.hpp
385   // for more details.
386   public boolean isIntrinsicAvailable(Executable method,
387                                       Executable compilationContext,
388                                       int compLevel) {
389       Objects.requireNonNull(method);
390       return isIntrinsicAvailable0(method, compilationContext, compLevel);
391   }
392   // If usage of the DisableIntrinsic flag is not expected (or the usage can be ignored),
393   // use the below method that does not require the compilation context as argument.
394   public boolean isIntrinsicAvailable(Executable method, int compLevel) {
395       return isIntrinsicAvailable(method, null, compLevel);
396   }
397   private native boolean isIntrinsicAvailable0(Executable method,
398                                                Executable compilationContext,
399                                                int compLevel);
400   public        int     deoptimizeMethod(Executable method) {
401     return deoptimizeMethod(method, false /*not osr*/);
402   }
403   private native int     deoptimizeMethod0(Executable method, boolean isOsr);
404   public         int     deoptimizeMethod(Executable method, boolean isOsr) {
405     Objects.requireNonNull(method);
406     return deoptimizeMethod0(method, isOsr);
407   }
408   public        void    makeMethodNotCompilable(Executable method) {
409     makeMethodNotCompilable(method, -1 /*any*/);
410   }
411   public        void    makeMethodNotCompilable(Executable method, int compLevel) {
412     makeMethodNotCompilable(method, compLevel, false /*not osr*/);
413   }
414   private native void    makeMethodNotCompilable0(Executable method, int compLevel, boolean isOsr);
415   public         void    makeMethodNotCompilable(Executable method, int compLevel, boolean isOsr) {
416     Objects.requireNonNull(method);
417     makeMethodNotCompilable0(method, compLevel, isOsr);
418   }
419   public        int     getMethodCompilationLevel(Executable method) {
420     return getMethodCompilationLevel(method, false /*not osr*/);
421   }
422   private native int     getMethodCompilationLevel0(Executable method, boolean isOsr);
423   public         int     getMethodCompilationLevel(Executable method, boolean isOsr) {
424     Objects.requireNonNull(method);
425     return getMethodCompilationLevel0(method, isOsr);
426   }
427   public         int     getMethodDecompileCount(Executable method) {
428     Objects.requireNonNull(method);
429     return getMethodDecompileCount0(method);
430   }
431   private native int     getMethodDecompileCount0(Executable method);
432   // Get the total trap count of a method. If the trap count for a specific reason
433   // did overflow, this includes the overflow trap count of the method.
434   public         int     getMethodTrapCount(Executable method) {
435     Objects.requireNonNull(method);
436     return getMethodTrapCount0(method, null);
437   }
438   // Get the trap count of a method for a specific reason. If the trap count for
439   // that reason did overflow, this includes the overflow trap count of the method.
440   public         int     getMethodTrapCount(Executable method, String reason) {
441     Objects.requireNonNull(method);
442     return getMethodTrapCount0(method, reason);
443   }
444   private native int     getMethodTrapCount0(Executable method, String reason);
445   // Get the total deopt count.
446   public         int     getDeoptCount() {
447     return getDeoptCount0(null, null);
448   }
449   // Get the deopt count for a specific reason and a specific action. If either
450   // one of 'reason' or 'action' is null, the method returns the sum of all
451   // deoptimizations with the specific 'action' or 'reason' respectively.
452   // If both arguments are null, the method returns the total deopt count.
453   public         int     getDeoptCount(String reason, String action) {
454     return getDeoptCount0(reason, action);
455   }
456   private native int     getDeoptCount0(String reason, String action);
457   private native boolean testSetDontInlineMethod0(Executable method, boolean value);
458   public         boolean testSetDontInlineMethod(Executable method, boolean value) {
459     Objects.requireNonNull(method);
460     return testSetDontInlineMethod0(method, value);
461   }
462   public        int     getCompileQueuesSize() {
463     return getCompileQueueSize(-1 /*any*/);
464   }
465   public native int     getCompileQueueSize(int compLevel);
466   private native boolean testSetForceInlineMethod0(Executable method, boolean value);
467   public         boolean testSetForceInlineMethod(Executable method, boolean value) {
468     Objects.requireNonNull(method);
469     return testSetForceInlineMethod0(method, value);
470   }
471   public        boolean enqueueMethodForCompilation(Executable method, int compLevel) {
472     return enqueueMethodForCompilation(method, compLevel, -1 /*InvocationEntryBci*/);
473   }
474   private native boolean enqueueMethodForCompilation0(Executable method, int compLevel, int entry_bci);
475   public  boolean enqueueMethodForCompilation(Executable method, int compLevel, int entry_bci) {
476     Objects.requireNonNull(method);
477     return enqueueMethodForCompilation0(method, compLevel, entry_bci);
478   }
479   private native boolean enqueueInitializerForCompilation0(Class<?> aClass, int compLevel);
480   public  boolean enqueueInitializerForCompilation(Class<?> aClass, int compLevel) {
481     Objects.requireNonNull(aClass);
482     return enqueueInitializerForCompilation0(aClass, compLevel);
483   }
484   private native void    clearMethodState0(Executable method);
485   public  native void    markMethodProfiled(Executable method);
486   public         void    clearMethodState(Executable method) {
487     Objects.requireNonNull(method);
488     clearMethodState0(method);
489   }
490   public native void    lockCompilation();
491   public native void    unlockCompilation();
492   private native int     getMethodEntryBci0(Executable method);
493   public         int     getMethodEntryBci(Executable method) {
494     Objects.requireNonNull(method);
495     return getMethodEntryBci0(method);
496   }
497   private native Object[] getNMethod0(Executable method, boolean isOsr);
498   public         Object[] getNMethod(Executable method, boolean isOsr) {
499     Objects.requireNonNull(method);
500     return getNMethod0(method, isOsr);
501   }
502   public native long    allocateCodeBlob(int size, int type);
503   public        long    allocateCodeBlob(long size, int type) {
504       int intSize = (int) size;
505       if ((long) intSize != size || size < 0) {
506           throw new IllegalArgumentException(
507                 "size argument has illegal value " + size);
508       }
509       return allocateCodeBlob( intSize, type);
510   }
511   public native void    freeCodeBlob(long addr);
512   public native Object[] getCodeHeapEntries(int type);
513   public native int     getCompilationActivityMode();
514   private native long getMethodData0(Executable method);
515   public         long getMethodData(Executable method) {
516     Objects.requireNonNull(method);
517     return getMethodData0(method);
518   }
519   public native Object[] getCodeBlob(long addr);
520 
521   private native void clearInlineCaches0(boolean preserve_static_stubs);
522   public void clearInlineCaches() {
523     clearInlineCaches0(false);
524   }
525   public void clearInlineCaches(boolean preserve_static_stubs) {
526     clearInlineCaches0(preserve_static_stubs);
527   }
528 
529   // Intered strings
530   public native boolean isInStringTable(String str);
531 
532   // Memory
533   public native void readReservedMemory();
534   public native long allocateMetaspace(ClassLoader classLoader, long size);
535   public native long incMetaspaceCapacityUntilGC(long increment);
536   public native long metaspaceCapacityUntilGC();
537   public native long metaspaceSharedRegionAlignment();
538 
539   public native void cleanMetaspaces();
540 
541   // Metaspace Arena Tests
542   public native long createMetaspaceTestContext(long commit_limit, long reserve_limit);
543   public native void destroyMetaspaceTestContext(long context);
544   public native void purgeMetaspaceTestContext(long context);
545   public native void printMetaspaceTestContext(long context);
546   public native long getTotalCommittedWordsInMetaspaceTestContext(long context);
547   public native long getTotalUsedWordsInMetaspaceTestContext(long context);
548   public native long createArenaInTestContext(long context, boolean is_micro);
549   public native void destroyMetaspaceTestArena(long arena);
550   public native long allocateFromMetaspaceTestArena(long arena, long word_size);
551   public native void deallocateToMetaspaceTestArena(long arena, long p, long word_size);
552 
553   public native long maxMetaspaceAllocationSize();
554 
555   // Don't use these methods directly
556   // Use jdk.test.whitebox.gc.GC class instead.
557   public native boolean isGCSupported(int name);
558   public native boolean isGCSupportedByJVMCICompiler(int name);
559   public native boolean isGCSelected(int name);
560   public native boolean isGCSelectedErgonomically();
561 
562   // Force Young GC
563   public native void youngGC();
564 
565   // Force Full GC
566   public native void fullGC();
567 
568   // Returns true if the current GC supports concurrent collection control.
569   public native boolean supportsConcurrentGCBreakpoints();
570 
571   private void checkConcurrentGCBreakpointsSupported() {
572     if (!supportsConcurrentGCBreakpoints()) {
573       throw new UnsupportedOperationException("Concurrent GC breakpoints not supported");
574     }
575   }
576 
577   private native void concurrentGCAcquireControl0();
578   private native void concurrentGCReleaseControl0();
579   private native void concurrentGCRunToIdle0();
580   private native boolean concurrentGCRunTo0(String breakpoint);
581 
582   private static boolean concurrentGCIsControlled = false;
583   private void checkConcurrentGCIsControlled() {
584     if (!concurrentGCIsControlled) {
585       throw new IllegalStateException("Not controlling concurrent GC");
586     }
587   }
588 
589   // All collectors supporting concurrent GC breakpoints are expected
590   // to provide at least the following breakpoints.
591   public final String AFTER_MARKING_STARTED = "AFTER MARKING STARTED";
592   public final String BEFORE_MARKING_COMPLETED = "BEFORE MARKING COMPLETED";
593 
594   // Collectors supporting concurrent GC breakpoints that do reference
595   // processing concurrently should provide the following breakpoint.
596   public final String AFTER_CONCURRENT_REFERENCE_PROCESSING_STARTED =
597     "AFTER CONCURRENT REFERENCE PROCESSING STARTED";
598 
599   // G1 specific GC breakpoints.
600   public final String G1_AFTER_REBUILD_STARTED = "AFTER REBUILD STARTED";
601   public final String G1_BEFORE_REBUILD_COMPLETED = "BEFORE REBUILD COMPLETED";
602   public final String G1_AFTER_CLEANUP_STARTED = "AFTER CLEANUP STARTED";
603   public final String G1_BEFORE_CLEANUP_COMPLETED = "BEFORE CLEANUP COMPLETED";
604 
605   public void concurrentGCAcquireControl() {
606     checkConcurrentGCBreakpointsSupported();
607     if (concurrentGCIsControlled) {
608       throw new IllegalStateException("Already controlling concurrent GC");
609     }
610     concurrentGCAcquireControl0();
611     concurrentGCIsControlled = true;
612   }
613 
614   public void concurrentGCReleaseControl() {
615     checkConcurrentGCBreakpointsSupported();
616     concurrentGCReleaseControl0();
617     concurrentGCIsControlled = false;
618   }
619 
620   // Keep concurrent GC idle.  Release from breakpoint.
621   public void concurrentGCRunToIdle() {
622     checkConcurrentGCBreakpointsSupported();
623     checkConcurrentGCIsControlled();
624     concurrentGCRunToIdle0();
625   }
626 
627   // Allow concurrent GC to run to breakpoint.
628   // Throws IllegalStateException if reached end of cycle first.
629   public void concurrentGCRunTo(String breakpoint) {
630     concurrentGCRunTo(breakpoint, true);
631   }
632 
633   // Allow concurrent GC to run to breakpoint.
634   // Returns true if reached breakpoint.  If reached end of cycle first,
635   // then throws IllegalStateException if errorIfFail is true, returning
636   // false otherwise.
637   public boolean concurrentGCRunTo(String breakpoint, boolean errorIfFail) {
638     checkConcurrentGCBreakpointsSupported();
639     checkConcurrentGCIsControlled();
640     if (breakpoint == null) {
641       throw new NullPointerException("null breakpoint");
642     } else if (concurrentGCRunTo0(breakpoint)) {
643       return true;
644     } else if (errorIfFail) {
645       throw new IllegalStateException("Missed requested breakpoint \"" + breakpoint + "\"");
646     } else {
647       return false;
648     }
649   }
650 
651   // Tests on ReservedSpace/VirtualSpace classes
652   public native int stressVirtualSpaceResize(long reservedSpaceSize, long magnitude, long iterations);
653   public native void readFromNoaccessArea();
654   public native long getThreadStackSize();
655   public native long getThreadRemainingStackSize();
656 
657   // CPU features
658   public native String getCPUFeatures();
659 
660   // VM flags
661   public native boolean isConstantVMFlag(String name);
662   public native boolean isDefaultVMFlag(String name);
663   public native boolean isLockedVMFlag(String name);
664   public native void    setBooleanVMFlag(String name, boolean value);
665   public native void    setIntVMFlag(String name, long value);
666   public native void    setUintVMFlag(String name, long value);
667   public native void    setIntxVMFlag(String name, long value);
668   public native void    setUintxVMFlag(String name, long value);
669   public native void    setUint64VMFlag(String name, long value);
670   public native void    setSizeTVMFlag(String name, long value);
671   public native void    setStringVMFlag(String name, String value);
672   public native void    setDoubleVMFlag(String name, double value);
673   public native Boolean getBooleanVMFlag(String name);
674   public native Long    getIntVMFlag(String name);
675   public native Long    getUintVMFlag(String name);
676   public native Long    getIntxVMFlag(String name);
677   public native Long    getUintxVMFlag(String name);
678   public native Long    getUint64VMFlag(String name);
679   public native Long    getSizeTVMFlag(String name);
680   public native String  getStringVMFlag(String name);
681   public native Double  getDoubleVMFlag(String name);
682   private final List<Function<String,Object>> flagsGetters = Arrays.asList(
683     this::getBooleanVMFlag, this::getIntVMFlag, this::getUintVMFlag,
684     this::getIntxVMFlag, this::getUintxVMFlag, this::getUint64VMFlag,
685     this::getSizeTVMFlag, this::getStringVMFlag, this::getDoubleVMFlag);
686 
687   public Object getVMFlag(String name) {
688     return flagsGetters.stream()
689                        .map(f -> f.apply(name))
690                        .filter(x -> x != null)
691                        .findAny()
692                        .orElse(null);
693   }
694 
695   // Jigsaw
696   public native void DefineModule(Object module, boolean is_open, String version,
697                                   String location, Object[] packages);
698   public native void AddModuleExports(Object from_module, String pkg, Object to_module);
699   public native void AddReadsModule(Object from_module, Object source_module);
700   public native void AddModuleExportsToAllUnnamed(Object module, String pkg);
701   public native void AddModuleExportsToAll(Object module, String pkg);
702 
703   public native int getCDSOffsetForName0(String name);
704   public int getCDSOffsetForName(String name) throws Exception {
705     int offset = getCDSOffsetForName0(name);
706     if (offset == -1) {
707       throw new RuntimeException(name + " not found");
708     }
709     return offset;
710   }
711   public native int getCDSConstantForName0(String name);
712   public int getCDSConstantForName(String name) throws Exception {
713     int constant = getCDSConstantForName0(name);
714     if (constant == -1) {
715       throw new RuntimeException(name + " not found");
716     }
717     return constant;
718   }
719   public native Boolean getMethodBooleanOption(Executable method, String name);
720   public native Long    getMethodIntxOption(Executable method, String name);
721   public native Long    getMethodUintxOption(Executable method, String name);
722   public native Double  getMethodDoubleOption(Executable method, String name);
723   public native String  getMethodStringOption(Executable method, String name);
724   private final List<BiFunction<Executable,String,Object>> methodOptionGetters
725       = Arrays.asList(this::getMethodBooleanOption, this::getMethodIntxOption,
726           this::getMethodUintxOption, this::getMethodDoubleOption,
727           this::getMethodStringOption);
728 
729   public Object getMethodOption(Executable method, String name) {
730     return methodOptionGetters.stream()
731                               .map(f -> f.apply(method, name))
732                               .filter(x -> x != null)
733                               .findAny()
734                               .orElse(null);
735   }
736 
737   // Sharing & archiving
738   public native int     getCDSGenericHeaderMinVersion();
739   public native int     getCurrentCDSVersion();
740   public native String  getDefaultArchivePath();
741   public native boolean cdsMemoryMappingFailed();
742   public native boolean isSharingEnabled();
743   public native boolean isSharedClass(Class<?> c);
744   public native boolean areSharedStringsMapped();
745   public native boolean isSharedInternedString(String s);
746   public native boolean isCDSIncluded();
747   public native boolean isJFRIncluded();
748   public native boolean isDTraceIncluded();
749   public native boolean canWriteJavaHeapArchive();
750   public native void    linkClass(Class<?> c);
751   public native boolean areOpenArchiveHeapObjectsMapped();
752 
753   // Compiler Directive
754   public native int addCompilerDirective(String compDirect);
755   public native void removeCompilerDirective(int count);
756 
757   // Handshakes
758   public native int handshakeWalkStack(Thread t, boolean all_threads);
759   public native boolean handshakeReadMonitors(Thread t);
760   public native void asyncHandshakeWalkStack(Thread t);
761 
762   public native void lockAndBlock(boolean suspender);
763 
764   // Returns true on linux if library has the noexecstack flag set.
765   public native boolean checkLibSpecifiesNoexecstack(String libfilename);
766 
767   // Container testing
768   public native boolean isContainerized();
769   public native int validateCgroup(String procCgroups,
770                                    String procSelfCgroup,
771                                    String procSelfMountinfo);
772   public native void printOsInfo();
773   public native long hostPhysicalMemory();
774   public native long hostPhysicalSwap();
775 
776   // Decoder
777   public native void disableElfSectionCache();
778 
779   // Resolved Method Table
780   public native long resolvedMethodItemsCount();
781 
782   // Protection Domain Table
783   public native int protectionDomainRemovedCount();
784 
785   public native int getKlassMetadataSize(Class<?> c);
786 
787   // ThreadSMR GC safety check for threadObj
788   public native void checkThreadObjOfTerminatingThread(Thread target);
789 
790   // libc name
791   public native String getLibcName();
792 
793   // Walk stack frames of current thread
794   public native void verifyFrames(boolean log, boolean updateRegisterMap);
795 
796   public native boolean isJVMTIIncluded();
797 
798   public native void waitUnsafe(int time_ms);
799 
800   public native void lockCritical();
801 
802   public native void unlockCritical();
803 
804   public native void pinObject(Object o);
805 
806   public native void unpinObject(Object o);
807 
808   public native boolean setVirtualThreadsNotifyJvmtiMode(boolean enabled);
809 
810   public native void preTouchMemory(long addr, long size);
811 }