1 /*
  2  * Copyright (c) 2012, 2024, 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 int getLockStackCapacity();
123 
124   public native boolean supportsRecursiveLightweightLocking();
125 
126   public native void forceSafepoint();
127 
128   public native void forceClassLoaderStatsSafepoint();
129 
130   private native long getConstantPool0(Class<?> aClass);
131   public         long getConstantPool(Class<?> aClass) {
132     Objects.requireNonNull(aClass);
133     return getConstantPool0(aClass);
134   }
135 
136   private native int getConstantPoolCacheIndexTag0();
137   public         int getConstantPoolCacheIndexTag() {
138     return getConstantPoolCacheIndexTag0();
139   }
140 
141   private native int getConstantPoolCacheLength0(Class<?> aClass);
142   public         int getConstantPoolCacheLength(Class<?> aClass) {
143     Objects.requireNonNull(aClass);
144     return getConstantPoolCacheLength0(aClass);
145   }
146 
147   private native Object[] getResolvedReferences0(Class<?> aClass);
148   public         Object[] getResolvedReferences(Class<?> aClass) {
149     Objects.requireNonNull(aClass);
150     return getResolvedReferences0(aClass);
151   }
152 
153   private native int remapInstructionOperandFromCPCache0(Class<?> aClass, int index);
154   public         int remapInstructionOperandFromCPCache(Class<?> aClass, int index) {
155     Objects.requireNonNull(aClass);
156     return remapInstructionOperandFromCPCache0(aClass, index);
157   }
158 
159   private native int encodeConstantPoolIndyIndex0(int index);
160   public         int encodeConstantPoolIndyIndex(int index) {
161     return encodeConstantPoolIndyIndex0(index);
162   }
163 
164   private native int getIndyInfoLength0(Class<?> aClass);
165   public         int getIndyInfoLength(Class<?> aClass) {
166     Objects.requireNonNull(aClass);
167     return getIndyInfoLength0(aClass);
168   }
169 
170   private native int getIndyCPIndex0(Class<?> aClass, int index);
171   public         int getIndyCPIndex(Class<?> aClass, int index) {
172     Objects.requireNonNull(aClass);
173     return getIndyCPIndex0(aClass, index);
174   }
175 
176   // JVMTI
177   private native void addToBootstrapClassLoaderSearch0(String segment);
178   public         void addToBootstrapClassLoaderSearch(String segment){
179     Objects.requireNonNull(segment);
180     addToBootstrapClassLoaderSearch0(segment);
181   }
182 
183   private native void addToSystemClassLoaderSearch0(String segment);
184   public         void addToSystemClassLoaderSearch(String segment) {
185     Objects.requireNonNull(segment);
186     addToSystemClassLoaderSearch0(segment);
187   }
188 
189   // G1
190 
191   public native boolean g1InConcurrentMark();
192   public native int g1CompletedConcurrentMarkCycles();
193 
194   // Perform a complete concurrent GC cycle, using concurrent GC breakpoints.
195   // Completes any in-progress cycle before performing the requested cycle.
196   // Returns true if the cycle completed successfully.  If the cycle was not
197   // successful (e.g. it was aborted), then throws RuntimeException if
198   // errorIfFail is true, returning false otherwise.
199   public boolean g1RunConcurrentGC(boolean errorIfFail) {
200     try {
201       // Take control, waiting until any in-progress cycle completes.
202       concurrentGCAcquireControl();
203       int count = g1CompletedConcurrentMarkCycles();
204       concurrentGCRunTo(AFTER_MARKING_STARTED, false);
205       concurrentGCRunToIdle();
206       if (count < g1CompletedConcurrentMarkCycles()) {
207         return true;
208       } else if (errorIfFail) {
209         throw new RuntimeException("Concurrent GC aborted");
210       } else {
211         return false;
212       }
213     } finally {
214       concurrentGCReleaseControl();
215     }
216   }
217 
218   public void g1RunConcurrentGC() {
219     g1RunConcurrentGC(true);
220   }
221 
222   // Start a concurrent GC cycle, using concurrent GC breakpoints.
223   // The concurrent GC will continue in parallel with the caller.
224   // Completes any in-progress cycle before starting the requested cycle.
225   public void g1StartConcurrentGC() {
226     try {
227       // Take control, waiting until any in-progress cycle completes.
228       concurrentGCAcquireControl();
229       concurrentGCRunTo(AFTER_MARKING_STARTED, false);
230     } finally {
231       // Release control, permitting the cycle to complete.
232       concurrentGCReleaseControl();
233     }
234   }
235 
236   public native boolean g1HasRegionsToUncommit();
237   private native boolean g1IsHumongous0(Object o);
238   public         boolean g1IsHumongous(Object o) {
239     Objects.requireNonNull(o);
240     return g1IsHumongous0(o);
241   }
242 
243   private native boolean g1BelongsToHumongousRegion0(long adr);
244   public         boolean g1BelongsToHumongousRegion(long adr) {
245     if (adr == 0) {
246       throw new IllegalArgumentException("adr argument should not be null");
247     }
248     return g1BelongsToHumongousRegion0(adr);
249   }
250 
251 
252   private native boolean g1BelongsToFreeRegion0(long adr);
253   public         boolean g1BelongsToFreeRegion(long adr) {
254     if (adr == 0) {
255       throw new IllegalArgumentException("adr argument should not be null");
256     }
257     return g1BelongsToFreeRegion0(adr);
258   }
259 
260   public native long    g1NumMaxRegions();
261   public native long    g1NumFreeRegions();
262   public native int     g1RegionSize();
263   public native MemoryUsage g1AuxiliaryMemoryUsage();
264   private  native Object[]    parseCommandLine0(String commandline, char delim, DiagnosticCommand[] args);
265   public          Object[]    parseCommandLine(String commandline, char delim, DiagnosticCommand[] args) {
266     Objects.requireNonNull(args);
267     return parseCommandLine0(commandline, delim, args);
268   }
269 
270   public native int g1ActiveMemoryNodeCount();
271   public native int[] g1MemoryNodeIds();
272 
273   // Parallel GC
274   public native long psVirtualSpaceAlignment();
275   public native long psHeapGenerationAlignment();
276 
277   /**
278    * Enumerates old regions with liveness less than specified and produces some statistics
279    * @param liveness percent of region's liveness (live_objects / total_region_size * 100).
280    * @return long[3] array where long[0] - total count of old regions
281    *                             long[1] - total memory of old regions
282    *                             long[2] - lowest estimation of total memory of old regions to be freed (non-full
283    *                             regions are not included)
284    */
285   public native long[] g1GetMixedGCInfo(int liveness);
286 
287   // NMT
288   public native long NMTMalloc(long size);
289   public native void NMTFree(long mem);
290   public native long NMTReserveMemory(long size);
291   public native long NMTAttemptReserveMemoryAt(long addr, long size);
292   public native void NMTCommitMemory(long addr, long size);
293   public native void NMTUncommitMemory(long addr, long size);
294   public native void NMTReleaseMemory(long addr, long size);
295   public native long NMTMallocWithPseudoStack(long size, int index);
296   public native long NMTMallocWithPseudoStackAndType(long size, int index, int type);
297   public native int NMTGetHashSize();
298   public native long NMTNewArena(long initSize);
299   public native void NMTFreeArena(long arena);
300   public native void NMTArenaMalloc(long arena, long size);
301 
302   // Compiler
303   public native boolean isC2OrJVMCIIncluded();
304   public native boolean isJVMCISupportedByGC();
305 
306   public native int     matchesMethod(Executable method, String pattern);
307   public native int     matchesInline(Executable method, String pattern);
308   public native boolean shouldPrintAssembly(Executable method, int comp_level);
309   public native int     deoptimizeFrames(boolean makeNotEntrant);
310   public native boolean isFrameDeoptimized(int depth);
311   public native void    deoptimizeAll();
312 
313   public        boolean isMethodCompiled(Executable method) {
314     return isMethodCompiled(method, false /*not osr*/);
315   }
316   private native boolean isMethodCompiled0(Executable method, boolean isOsr);
317   public         boolean isMethodCompiled(Executable method, boolean isOsr){
318     Objects.requireNonNull(method);
319     return isMethodCompiled0(method, isOsr);
320   }
321   public        boolean isMethodCompilable(Executable method) {
322     return isMethodCompilable(method, -1 /*any*/);
323   }
324   public        boolean isMethodCompilable(Executable method, int compLevel) {
325     return isMethodCompilable(method, compLevel, false /*not osr*/);
326   }
327   private native boolean isMethodCompilable0(Executable method, int compLevel, boolean isOsr);
328   public         boolean isMethodCompilable(Executable method, int compLevel, boolean isOsr) {
329     Objects.requireNonNull(method);
330     return isMethodCompilable0(method, compLevel, isOsr);
331   }
332   private native boolean isMethodQueuedForCompilation0(Executable method);
333   public         boolean isMethodQueuedForCompilation(Executable method) {
334     Objects.requireNonNull(method);
335     return isMethodQueuedForCompilation0(method);
336   }
337   // Determine if the compiler corresponding to the compilation level 'compLevel'
338   // and to the compilation context 'compilation_context' provides an intrinsic
339   // for the method 'method'. An intrinsic is available for method 'method' if:
340   //  - the intrinsic is enabled (by using the appropriate command-line flag) and
341   //  - the platform on which the VM is running provides the instructions necessary
342   //    for the compiler to generate the intrinsic code.
343   //
344   // The compilation context is related to using the DisableIntrinsic flag on a
345   // per-method level, see hotspot/src/share/vm/compiler/abstractCompiler.hpp
346   // for more details.
347   public boolean isIntrinsicAvailable(Executable method,
348                                       Executable compilationContext,
349                                       int compLevel) {
350       Objects.requireNonNull(method);
351       return isIntrinsicAvailable0(method, compilationContext, compLevel);
352   }
353   // If usage of the DisableIntrinsic flag is not expected (or the usage can be ignored),
354   // use the below method that does not require the compilation context as argument.
355   public boolean isIntrinsicAvailable(Executable method, int compLevel) {
356       return isIntrinsicAvailable(method, null, compLevel);
357   }
358   private native boolean isIntrinsicAvailable0(Executable method,
359                                                Executable compilationContext,
360                                                int compLevel);
361   public        int     deoptimizeMethod(Executable method) {
362     return deoptimizeMethod(method, false /*not osr*/);
363   }
364   private native int     deoptimizeMethod0(Executable method, boolean isOsr);
365   public         int     deoptimizeMethod(Executable method, boolean isOsr) {
366     Objects.requireNonNull(method);
367     return deoptimizeMethod0(method, isOsr);
368   }
369   public        void    makeMethodNotCompilable(Executable method) {
370     makeMethodNotCompilable(method, -1 /*any*/);
371   }
372   public        void    makeMethodNotCompilable(Executable method, int compLevel) {
373     makeMethodNotCompilable(method, compLevel, false /*not osr*/);
374   }
375   private native void    makeMethodNotCompilable0(Executable method, int compLevel, boolean isOsr);
376   public         void    makeMethodNotCompilable(Executable method, int compLevel, boolean isOsr) {
377     Objects.requireNonNull(method);
378     makeMethodNotCompilable0(method, compLevel, isOsr);
379   }
380   public        int     getMethodCompilationLevel(Executable method) {
381     return getMethodCompilationLevel(method, false /*not osr*/);
382   }
383   private native int     getMethodCompilationLevel0(Executable method, boolean isOsr);
384   public         int     getMethodCompilationLevel(Executable method, boolean isOsr) {
385     Objects.requireNonNull(method);
386     return getMethodCompilationLevel0(method, isOsr);
387   }
388   public         int     getMethodDecompileCount(Executable method) {
389     Objects.requireNonNull(method);
390     return getMethodDecompileCount0(method);
391   }
392   private native int     getMethodDecompileCount0(Executable method);
393   // Get the total trap count of a method. If the trap count for a specific reason
394   // did overflow, this includes the overflow trap count of the method.
395   public         int     getMethodTrapCount(Executable method) {
396     Objects.requireNonNull(method);
397     return getMethodTrapCount0(method, null);
398   }
399   // Get the trap count of a method for a specific reason. If the trap count for
400   // that reason did overflow, this includes the overflow trap count of the method.
401   public         int     getMethodTrapCount(Executable method, String reason) {
402     Objects.requireNonNull(method);
403     return getMethodTrapCount0(method, reason);
404   }
405   private native int     getMethodTrapCount0(Executable method, String reason);
406   // Get the total deopt count.
407   public         int     getDeoptCount() {
408     return getDeoptCount0(null, null);
409   }
410   // Get the deopt count for a specific reason and a specific action. If either
411   // one of 'reason' or 'action' is null, the method returns the sum of all
412   // deoptimizations with the specific 'action' or 'reason' respectively.
413   // If both arguments are null, the method returns the total deopt count.
414   public         int     getDeoptCount(String reason, String action) {
415     return getDeoptCount0(reason, action);
416   }
417   private native int     getDeoptCount0(String reason, String action);
418   private native boolean testSetDontInlineMethod0(Executable method, boolean value);
419   public         boolean testSetDontInlineMethod(Executable method, boolean value) {
420     Objects.requireNonNull(method);
421     return testSetDontInlineMethod0(method, value);
422   }
423   public        int     getCompileQueuesSize() {
424     return getCompileQueueSize(-1 /*any*/);
425   }
426   public native int     getCompileQueueSize(int compLevel);
427   private native boolean testSetForceInlineMethod0(Executable method, boolean value);
428   public         boolean testSetForceInlineMethod(Executable method, boolean value) {
429     Objects.requireNonNull(method);
430     return testSetForceInlineMethod0(method, value);
431   }
432   public        boolean enqueueMethodForCompilation(Executable method, int compLevel) {
433     return enqueueMethodForCompilation(method, compLevel, -1 /*InvocationEntryBci*/);
434   }
435   private native boolean enqueueMethodForCompilation0(Executable method, int compLevel, int entry_bci);
436   public  boolean enqueueMethodForCompilation(Executable method, int compLevel, int entry_bci) {
437     Objects.requireNonNull(method);
438     return enqueueMethodForCompilation0(method, compLevel, entry_bci);
439   }
440   private native boolean enqueueInitializerForCompilation0(Class<?> aClass, int compLevel);
441   public  boolean enqueueInitializerForCompilation(Class<?> aClass, int compLevel) {
442     Objects.requireNonNull(aClass);
443     return enqueueInitializerForCompilation0(aClass, compLevel);
444   }
445   private native void    clearMethodState0(Executable method);
446   public  native void    markMethodProfiled(Executable method);
447   public         void    clearMethodState(Executable method) {
448     Objects.requireNonNull(method);
449     clearMethodState0(method);
450   }
451   public native void    lockCompilation();
452   public native void    unlockCompilation();
453   private native int     getMethodEntryBci0(Executable method);
454   public         int     getMethodEntryBci(Executable method) {
455     Objects.requireNonNull(method);
456     return getMethodEntryBci0(method);
457   }
458   private native Object[] getNMethod0(Executable method, boolean isOsr);
459   public         Object[] getNMethod(Executable method, boolean isOsr) {
460     Objects.requireNonNull(method);
461     return getNMethod0(method, isOsr);
462   }
463   public native long    allocateCodeBlob(int size, int type);
464   public        long    allocateCodeBlob(long size, int type) {
465       int intSize = (int) size;
466       if ((long) intSize != size || size < 0) {
467           throw new IllegalArgumentException(
468                 "size argument has illegal value " + size);
469       }
470       return allocateCodeBlob( intSize, type);
471   }
472   public native void    freeCodeBlob(long addr);
473   public native Object[] getCodeHeapEntries(int type);
474   public native int     getCompilationActivityMode();
475   private native long getMethodData0(Executable method);
476   public         long getMethodData(Executable method) {
477     Objects.requireNonNull(method);
478     return getMethodData0(method);
479   }
480   public native Object[] getCodeBlob(long addr);
481 
482   private native void clearInlineCaches0(boolean preserve_static_stubs);
483   public void clearInlineCaches() {
484     clearInlineCaches0(false);
485   }
486   public void clearInlineCaches(boolean preserve_static_stubs) {
487     clearInlineCaches0(preserve_static_stubs);
488   }
489 
490   // Intered strings
491   public native boolean isInStringTable(String str);
492 
493   // Memory
494   public native void readReservedMemory();
495   public native long allocateMetaspace(ClassLoader classLoader, long size);
496   public native long incMetaspaceCapacityUntilGC(long increment);
497   public native long metaspaceCapacityUntilGC();
498   public native long metaspaceSharedRegionAlignment();
499 
500   public native void cleanMetaspaces();
501 
502   // Metaspace Arena Tests
503   public native long createMetaspaceTestContext(long commit_limit, long reserve_limit);
504   public native void destroyMetaspaceTestContext(long context);
505   public native void purgeMetaspaceTestContext(long context);
506   public native void printMetaspaceTestContext(long context);
507   public native long getTotalCommittedWordsInMetaspaceTestContext(long context);
508   public native long getTotalUsedWordsInMetaspaceTestContext(long context);
509   public native long createArenaInTestContext(long context, boolean is_micro);
510   public native void destroyMetaspaceTestArena(long arena);
511   public native long allocateFromMetaspaceTestArena(long arena, long word_size);
512   public native void deallocateToMetaspaceTestArena(long arena, long p, long word_size);
513 
514   public native long maxMetaspaceAllocationSize();
515 
516   // Don't use these methods directly
517   // Use jdk.test.whitebox.gc.GC class instead.
518   public native boolean isGCSupported(int name);
519   public native boolean isGCSupportedByJVMCICompiler(int name);
520   public native boolean isGCSelected(int name);
521   public native boolean isGCSelectedErgonomically();
522 
523   // Force Young GC
524   public native void youngGC();
525 
526   // Force Full GC
527   public native void fullGC();
528 
529   // Returns true if the current GC supports concurrent collection control.
530   public native boolean supportsConcurrentGCBreakpoints();
531 
532   private void checkConcurrentGCBreakpointsSupported() {
533     if (!supportsConcurrentGCBreakpoints()) {
534       throw new UnsupportedOperationException("Concurrent GC breakpoints not supported");
535     }
536   }
537 
538   private native void concurrentGCAcquireControl0();
539   private native void concurrentGCReleaseControl0();
540   private native void concurrentGCRunToIdle0();
541   private native boolean concurrentGCRunTo0(String breakpoint);
542 
543   private static boolean concurrentGCIsControlled = false;
544   private void checkConcurrentGCIsControlled() {
545     if (!concurrentGCIsControlled) {
546       throw new IllegalStateException("Not controlling concurrent GC");
547     }
548   }
549 
550   // All collectors supporting concurrent GC breakpoints are expected
551   // to provide at least the following breakpoints.
552   public final String AFTER_MARKING_STARTED = "AFTER MARKING STARTED";
553   public final String BEFORE_MARKING_COMPLETED = "BEFORE MARKING COMPLETED";
554 
555   // Collectors supporting concurrent GC breakpoints that do reference
556   // processing concurrently should provide the following breakpoint.
557   public final String AFTER_CONCURRENT_REFERENCE_PROCESSING_STARTED =
558     "AFTER CONCURRENT REFERENCE PROCESSING STARTED";
559 
560   // G1 specific GC breakpoints.
561   public final String G1_AFTER_REBUILD_STARTED = "AFTER REBUILD STARTED";
562   public final String G1_BEFORE_REBUILD_COMPLETED = "BEFORE REBUILD COMPLETED";
563   public final String G1_AFTER_CLEANUP_STARTED = "AFTER CLEANUP STARTED";
564   public final String G1_BEFORE_CLEANUP_COMPLETED = "BEFORE CLEANUP COMPLETED";
565 
566   public void concurrentGCAcquireControl() {
567     checkConcurrentGCBreakpointsSupported();
568     if (concurrentGCIsControlled) {
569       throw new IllegalStateException("Already controlling concurrent GC");
570     }
571     concurrentGCAcquireControl0();
572     concurrentGCIsControlled = true;
573   }
574 
575   public void concurrentGCReleaseControl() {
576     checkConcurrentGCBreakpointsSupported();
577     concurrentGCReleaseControl0();
578     concurrentGCIsControlled = false;
579   }
580 
581   // Keep concurrent GC idle.  Release from breakpoint.
582   public void concurrentGCRunToIdle() {
583     checkConcurrentGCBreakpointsSupported();
584     checkConcurrentGCIsControlled();
585     concurrentGCRunToIdle0();
586   }
587 
588   // Allow concurrent GC to run to breakpoint.
589   // Throws IllegalStateException if reached end of cycle first.
590   public void concurrentGCRunTo(String breakpoint) {
591     concurrentGCRunTo(breakpoint, true);
592   }
593 
594   // Allow concurrent GC to run to breakpoint.
595   // Returns true if reached breakpoint.  If reached end of cycle first,
596   // then throws IllegalStateException if errorIfFail is true, returning
597   // false otherwise.
598   public boolean concurrentGCRunTo(String breakpoint, boolean errorIfFail) {
599     checkConcurrentGCBreakpointsSupported();
600     checkConcurrentGCIsControlled();
601     if (breakpoint == null) {
602       throw new NullPointerException("null breakpoint");
603     } else if (concurrentGCRunTo0(breakpoint)) {
604       return true;
605     } else if (errorIfFail) {
606       throw new IllegalStateException("Missed requested breakpoint \"" + breakpoint + "\"");
607     } else {
608       return false;
609     }
610   }
611 
612   // Tests on ReservedSpace/VirtualSpace classes
613   public native int stressVirtualSpaceResize(long reservedSpaceSize, long magnitude, long iterations);
614   public native void readFromNoaccessArea();
615   public native long getThreadStackSize();
616   public native long getThreadRemainingStackSize();
617 
618   // CPU features
619   public native String getCPUFeatures();
620 
621   // VM flags
622   public native boolean isConstantVMFlag(String name);
623   public native boolean isDefaultVMFlag(String name);
624   public native boolean isLockedVMFlag(String name);
625   public native void    setBooleanVMFlag(String name, boolean value);
626   public native void    setIntVMFlag(String name, long value);
627   public native void    setUintVMFlag(String name, long value);
628   public native void    setIntxVMFlag(String name, long value);
629   public native void    setUintxVMFlag(String name, long value);
630   public native void    setUint64VMFlag(String name, long value);
631   public native void    setSizeTVMFlag(String name, long value);
632   public native void    setStringVMFlag(String name, String value);
633   public native void    setDoubleVMFlag(String name, double value);
634   public native Boolean getBooleanVMFlag(String name);
635   public native Long    getIntVMFlag(String name);
636   public native Long    getUintVMFlag(String name);
637   public native Long    getIntxVMFlag(String name);
638   public native Long    getUintxVMFlag(String name);
639   public native Long    getUint64VMFlag(String name);
640   public native Long    getSizeTVMFlag(String name);
641   public native String  getStringVMFlag(String name);
642   public native Double  getDoubleVMFlag(String name);
643   private final List<Function<String,Object>> flagsGetters = Arrays.asList(
644     this::getBooleanVMFlag, this::getIntVMFlag, this::getUintVMFlag,
645     this::getIntxVMFlag, this::getUintxVMFlag, this::getUint64VMFlag,
646     this::getSizeTVMFlag, this::getStringVMFlag, this::getDoubleVMFlag);
647 
648   public Object getVMFlag(String name) {
649     return flagsGetters.stream()
650                        .map(f -> f.apply(name))
651                        .filter(x -> x != null)
652                        .findAny()
653                        .orElse(null);
654   }
655 
656   // Jigsaw
657   public native void DefineModule(Object module, boolean is_open, String version,
658                                   String location, Object[] packages);
659   public native void AddModuleExports(Object from_module, String pkg, Object to_module);
660   public native void AddReadsModule(Object from_module, Object source_module);
661   public native void AddModuleExportsToAllUnnamed(Object module, String pkg);
662   public native void AddModuleExportsToAll(Object module, String pkg);
663 
664   public native int getCDSOffsetForName0(String name);
665   public int getCDSOffsetForName(String name) throws Exception {
666     int offset = getCDSOffsetForName0(name);
667     if (offset == -1) {
668       throw new RuntimeException(name + " not found");
669     }
670     return offset;
671   }
672   public native int getCDSConstantForName0(String name);
673   public int getCDSConstantForName(String name) throws Exception {
674     int constant = getCDSConstantForName0(name);
675     if (constant == -1) {
676       throw new RuntimeException(name + " not found");
677     }
678     return constant;
679   }
680   public native Boolean getMethodBooleanOption(Executable method, String name);
681   public native Long    getMethodIntxOption(Executable method, String name);
682   public native Long    getMethodUintxOption(Executable method, String name);
683   public native Double  getMethodDoubleOption(Executable method, String name);
684   public native String  getMethodStringOption(Executable method, String name);
685   private final List<BiFunction<Executable,String,Object>> methodOptionGetters
686       = Arrays.asList(this::getMethodBooleanOption, this::getMethodIntxOption,
687           this::getMethodUintxOption, this::getMethodDoubleOption,
688           this::getMethodStringOption);
689 
690   public Object getMethodOption(Executable method, String name) {
691     return methodOptionGetters.stream()
692                               .map(f -> f.apply(method, name))
693                               .filter(x -> x != null)
694                               .findAny()
695                               .orElse(null);
696   }
697 
698   // Sharing & archiving
699   public native int     getCDSGenericHeaderMinVersion();
700   public native int     getCurrentCDSVersion();
701   public native String  getDefaultArchivePath();
702   public native boolean cdsMemoryMappingFailed();
703   public native boolean isSharingEnabled();
704   public native boolean isSharedClass(Class<?> c);
705   public native boolean areSharedStringsMapped();
706   public native boolean isSharedInternedString(String s);
707   public native boolean isCDSIncluded();
708   public native boolean isJFRIncluded();
709   public native boolean isDTraceIncluded();
710   public native boolean canWriteJavaHeapArchive();
711   public native void    linkClass(Class<?> c);
712   public native boolean areOpenArchiveHeapObjectsMapped();
713 
714   // Compiler Directive
715   public native int addCompilerDirective(String compDirect);
716   public native void removeCompilerDirective(int count);
717 
718   // Handshakes
719   public native int handshakeWalkStack(Thread t, boolean all_threads);
720   public native boolean handshakeReadMonitors(Thread t);
721   public native void asyncHandshakeWalkStack(Thread t);
722 
723   public native void lockAndBlock(boolean suspender);
724 
725   // Returns true on linux if library has the noexecstack flag set.
726   public native boolean checkLibSpecifiesNoexecstack(String libfilename);
727 
728   // Container testing
729   public native boolean isContainerized();
730   public native int validateCgroup(String procCgroups,
731                                    String procSelfCgroup,
732                                    String procSelfMountinfo);
733   public native void printOsInfo();
734   public native long hostPhysicalMemory();
735   public native long hostPhysicalSwap();
736 
737   // Decoder
738   public native void disableElfSectionCache();
739 
740   // Resolved Method Table
741   public native long resolvedMethodItemsCount();
742 
743   // Protection Domain Table
744   public native int protectionDomainRemovedCount();
745 
746   public native int getKlassMetadataSize(Class<?> c);
747 
748   // ThreadSMR GC safety check for threadObj
749   public native void checkThreadObjOfTerminatingThread(Thread target);
750 
751   // libc name
752   public native String getLibcName();
753 
754   // Walk stack frames of current thread
755   public native void verifyFrames(boolean log, boolean updateRegisterMap);
756 
757   public native boolean isJVMTIIncluded();
758 
759   public native void waitUnsafe(int time_ms);
760 
761   public native void lockCritical();
762 
763   public native void unlockCritical();
764 
765   public native boolean setVirtualThreadsNotifyJvmtiMode(boolean enabled);
766 
767   public native void preTouchMemory(long addr, long size);
768 }