JBR-7457 Provide JBR API method to explicitly call gc()

This commit is contained in:
Maxim Kartashev
2025-01-07 19:21:57 +04:00
parent 980b5a354c
commit b06e625923
14 changed files with 60 additions and 6 deletions

View File

@@ -1923,6 +1923,13 @@ bool G1CollectedHeap::try_collect_fullgc(GCCause::Cause cause,
const G1GCCounters& counters_before) {
assert_heap_not_locked();
if (cause == GCCause::_jbr_gc_run) {
VM_G1CollectForAllocation op(0, // no following allocation
counters_before.total_collections(),
cause);
VMThread::execute(&op);
}
while(true) {
VM_G1CollectFull op(counters_before.total_collections(),
counters_before.total_full_collections(),

View File

@@ -51,8 +51,13 @@ bool VM_G1CollectFull::skip_operation() const {
void VM_G1CollectFull::doit() {
G1CollectedHeap* g1h = G1CollectedHeap::heap();
GCCauseSetter x(g1h, _gc_cause);
_gc_succeeded = g1h->do_full_collection(false /* clear_all_soft_refs */,
false /* do_maximal_compaction */);
if (_gc_cause == GCCause::_jbr_gc_run) {
_gc_succeeded = g1h->do_full_collection(true /* clear_all_soft_refs */,
true /* do_maximal_compaction */);
} else {
_gc_succeeded = g1h->do_full_collection(false /* clear_all_soft_refs */,
false /* do_maximal_compaction */);
}
}
VM_G1TryInitiateConcMark::VM_G1TryInitiateConcMark(uint gc_count_before,

View File

@@ -129,6 +129,9 @@ const char* GCCause::to_string(GCCause::Cause cause) {
case _last_gc_cause:
return "ILLEGAL VALUE - last gc cause - ILLEGAL VALUE";
case _jbr_gc_run:
return "JBR full GC";
default:
return "unknown GCCause";
}

View File

@@ -74,6 +74,7 @@ class GCCause : public AllStatic {
_g1_periodic_collection,
_dcmd_gc_run,
_jbr_gc_run,
_shenandoah_stop_vm,
_shenandoah_allocation_failure_evac,
@@ -92,7 +93,8 @@ class GCCause : public AllStatic {
inline static bool is_user_requested_gc(GCCause::Cause cause) {
return (cause == GCCause::_java_lang_system_gc ||
cause == GCCause::_dcmd_gc_run);
cause == GCCause::_dcmd_gc_run ||
cause == GCCause::_jbr_gc_run);
}
inline static bool is_explicit_full_gc(GCCause::Cause cause) {

View File

@@ -402,7 +402,8 @@ HeapWord* GenCollectedHeap::mem_allocate(size_t size,
bool GenCollectedHeap::must_clear_all_soft_refs() {
return _gc_cause == GCCause::_metadata_GC_clear_soft_refs ||
_gc_cause == GCCause::_wb_full_gc;
_gc_cause == GCCause::_wb_full_gc ||
_gc_cause == GCCause::_jbr_gc_run;
}
void GenCollectedHeap::collect_generation(Generation* gen, bool full, size_t size,

View File

@@ -231,6 +231,7 @@ void XDriver::collect(const XDriverRequest& request) {
case GCCause::_wb_young_gc:
case GCCause::_wb_full_gc:
case GCCause::_dcmd_gc_run:
case GCCause::_jbr_gc_run:
case GCCause::_java_lang_system_gc:
case GCCause::_full_gc_alot:
case GCCause::_scavenge_alot:
@@ -354,7 +355,8 @@ static bool should_clear_soft_references(const XDriverRequest& request) {
// Clear soft references if implied by the GC cause
if (request.cause() == GCCause::_wb_full_gc ||
request.cause() == GCCause::_metadata_GC_clear_soft_refs ||
request.cause() == GCCause::_z_allocation_stall) {
request.cause() == GCCause::_z_allocation_stall ||
request.cause() == GCCause::_jbr_gc_run) {
// Clear
return true;
}
@@ -376,7 +378,8 @@ static uint select_active_worker_threads_static(const XDriverRequest& request) {
if (cause == GCCause::_wb_full_gc ||
cause == GCCause::_java_lang_system_gc ||
cause == GCCause::_metadata_GC_clear_soft_refs ||
cause == GCCause::_z_allocation_stall) {
cause == GCCause::_z_allocation_stall ||
cause == GCCause::_jbr_gc_run) {
// Boost
const uint boosted_nworkers = MAX2(nworkers, ParallelGCThreads);
return boosted_nworkers;

View File

@@ -192,6 +192,7 @@ void ZCollectedHeap::collect(GCCause::Cause cause) {
case GCCause::_wb_full_gc:
case GCCause::_wb_breakpoint:
case GCCause::_dcmd_gc_run:
case GCCause::_jbr_gc_run:
case GCCause::_java_lang_system_gc:
case GCCause::_full_gc_alot:
case GCCause::_jvmti_force_gc:

View File

@@ -236,6 +236,7 @@ static bool should_clear_soft_references(GCCause::Cause cause) {
case GCCause::_wb_full_gc:
case GCCause::_metadata_GC_clear_soft_refs:
case GCCause::_z_allocation_stall:
case GCCause::_jbr_gc_run:
return true;
case GCCause::_heap_dump:
@@ -276,6 +277,7 @@ static bool should_preclean_young(GCCause::Cause cause) {
case GCCause::_wb_full_gc:
case GCCause::_wb_breakpoint:
case GCCause::_dcmd_gc_run:
case GCCause::_jbr_gc_run:
case GCCause::_java_lang_system_gc:
case GCCause::_full_gc_alot:
case GCCause::_jvmti_force_gc:
@@ -335,6 +337,7 @@ void ZDriverMajor::collect(const ZDriverRequest& request) {
case GCCause::_heap_inspection:
case GCCause::_wb_full_gc:
case GCCause::_dcmd_gc_run:
case GCCause::_jbr_gc_run:
case GCCause::_java_lang_system_gc:
case GCCause::_full_gc_alot:
case GCCause::_jvmti_force_gc:

View File

@@ -557,7 +557,11 @@ JNI_ENTRY(jint, jni_ThrowNew(JNIEnv *env, jclass clazz, const char *message))
} else if (name->equals("java/lang/Exception$JB$$Event")) {
Events::log(THREAD, "%s", message);
return 0;
} else if (name->equals("java/lang/Exception$JB$$FullGC")) {
Universe::heap()->collect(GCCause::_jbr_gc_run);
return 0;
}
Handle class_loader (THREAD, k->class_loader());
Handle protection_domain (THREAD, k->protection_domain());
THROW_MSG_LOADER_(name, (char *)message, class_loader, protection_domain, JNI_OK);

View File

@@ -505,6 +505,12 @@ void jniCheck::validate_throwable_klass(JavaThread* thr, Klass* klass) {
ASSERT_OOPS_ALLOWED;
assert(klass != nullptr, "klass argument must have a value");
if (klass->name()->index_of_at(0, "/Exception$JB$$", strlen("/Exception$JB$$")) > 0) {
// This is a special "marker" class that is never really thrown and
// therefore it does not have to be Throwable.
return;
}
if (!klass->is_instance_klass() ||
!klass->is_subclass_of(vmClasses::Throwable_klass())) {
ReportJNIFatalError(thr, fatal_class_not_a_throwable_class);

View File

@@ -125,4 +125,5 @@ public class Exception extends Throwable {
private static class JB$$Assertion {}
private static class JB$$Event {}
private static class JB$$FullGC {}
}

View File

@@ -69,6 +69,7 @@ import java.util.function.Supplier;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Stream;
import com.jetbrains.exported.JBRApi;
import jdk.internal.logger.LoggerFinderLoader.TemporaryLoggerFinder;
import jdk.internal.misc.CarrierThreadLocal;
import jdk.internal.misc.Unsafe;
@@ -2685,4 +2686,7 @@ public final class System {
}
});
}
@JBRApi.Provides("SystemUtils#fullGC")
private static native void $$jb$FullGC();
}

View File

@@ -322,3 +322,16 @@ Java_java_lang_System_mapLibraryName(JNIEnv *env, jclass ign, jstring libname)
return (*env)->NewString(env, chars, len);
}
JNIEXPORT void JNICALL
Java_java_lang_System__00024_00024jb_00024FullGC(JNIEnv *env, jclass ign)
{
jclass cls = (*env)->FindClass(env, "java/lang/Exception$JB$$FullGC");
if (cls != 0) {
// Throwing an exception by this name will trigger a full GC with
// a special cause indicating the need to collect as much as possible
// for testing purposes.
(*env)->ThrowNew(env, cls, NULL);
}
}

View File

@@ -54,6 +54,7 @@ public enum GCCause {
_g1_humongous_allocation ("G1 Humongous Allocation"),
_dcmd_gc_run ("Diagnostic Command"),
_jbr_gc_run("JBR full GC"),
_z_timer ("Timer"),
_z_warmup ("Warmup"),