Skip to content

Commit c82c50b

Browse files
committedJun 14, 2020
8245925: G1 allocates EDEN region after CDS has executed GC
Reviewed-by: jiangli, minqi, tschatzl
1 parent af83d6a commit c82c50b

File tree

7 files changed

+76
-21
lines changed

7 files changed

+76
-21
lines changed
 

‎src/hotspot/share/gc/g1/g1HeapVerifier.cpp

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -326,15 +326,14 @@ void G1HeapVerifier::verify_ready_for_archiving() {
326326
if (cl.has_holes()) {
327327
log_warning(gc, verify)("All free regions should be at the top end of the heap, but"
328328
" we found holes. This is probably caused by (unmovable) humongous"
329-
" allocations, and may lead to fragmentation while"
329+
" allocations or active GCLocker, and may lead to fragmentation while"
330330
" writing archive heap memory regions.");
331331
}
332332
if (cl.has_humongous()) {
333333
log_warning(gc, verify)("(Unmovable) humongous regions have been found and"
334334
" may lead to fragmentation while"
335335
" writing archive heap memory regions.");
336336
}
337-
assert(!cl.has_unexpected_holes(), "all holes should have been caused by humongous regions");
338337
}
339338

340339
class VerifyArchivePointerRegionClosure: public HeapRegionClosure {

‎src/hotspot/share/gc/shared/collectedHeap.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ void CollectedHeap::collect_as_vm_thread(GCCause::Cause cause) {
240240
do_full_collection(false); // don't clear all soft refs
241241
break;
242242
}
243+
case GCCause::_archive_time_gc:
243244
case GCCause::_metadata_GC_clear_soft_refs: {
244245
HandleMark hm;
245246
do_full_collection(true); // do clear all soft refs

‎src/hotspot/share/memory/heapShared.cpp

+20
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "classfile/symbolTable.hpp"
2929
#include "classfile/systemDictionaryShared.hpp"
3030
#include "classfile/vmSymbols.hpp"
31+
#include "gc/shared/gcLocker.hpp"
3132
#include "logging/log.hpp"
3233
#include "logging/logMessage.hpp"
3334
#include "logging/logStream.hpp"
@@ -186,6 +187,25 @@ void HeapShared::archive_klass_objects(Thread* THREAD) {
186187
}
187188
}
188189

190+
void HeapShared::run_full_gc_in_vm_thread() {
191+
if (is_heap_object_archiving_allowed()) {
192+
// Avoid fragmentation while archiving heap objects.
193+
// We do this inside a safepoint, so that no further allocation can happen after GC
194+
// has finished.
195+
if (GCLocker::is_active()) {
196+
// Just checking for safety ...
197+
// This should not happen during -Xshare:dump. If you see this, probably the Java core lib
198+
// has been modified such that JNI code is executed in some clean up threads after
199+
// we have finished class loading.
200+
log_warning(cds)("GC locker is held, unable to start extra compacting GC. This may produce suboptimal results.");
201+
} else {
202+
log_info(cds)("Run GC ...");
203+
Universe::heap()->collect_as_vm_thread(GCCause::_archive_time_gc);
204+
log_info(cds)("Run GC done");
205+
}
206+
}
207+
}
208+
189209
void HeapShared::archive_java_heap_objects(GrowableArray<MemRegion> *closed,
190210
GrowableArray<MemRegion> *open) {
191211
if (!is_heap_object_archiving_allowed()) {

‎src/hotspot/share/memory/heapShared.hpp

+2
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,8 @@ class HeapShared: AllStatic {
277277
#endif // INCLUDE_CDS_JAVA_HEAP
278278

279279
public:
280+
static void run_full_gc_in_vm_thread() NOT_CDS_JAVA_HEAP_RETURN;
281+
280282
static bool is_heap_object_archiving_allowed() {
281283
CDS_JAVA_HEAP_ONLY(return (UseG1GC && UseCompressedOops && UseCompressedClassPointers);)
282284
NOT_CDS_JAVA_HEAP(return false;)

‎src/hotspot/share/memory/metaspaceShared.cpp

+3-7
Original file line numberDiff line numberDiff line change
@@ -1638,6 +1638,7 @@ void VM_PopulateDumpSharedSpace::relocate_to_requested_base_address(CHeapBitMap*
16381638
}
16391639

16401640
void VM_PopulateDumpSharedSpace::doit() {
1641+
HeapShared::run_full_gc_in_vm_thread();
16411642
CHeapBitMap ptrmap;
16421643
MetaspaceShared::initialize_ptr_marker(&ptrmap);
16431644

@@ -1956,14 +1957,9 @@ void MetaspaceShared::preload_and_dump(TRAPS) {
19561957
link_and_cleanup_shared_classes(CATCH);
19571958
log_info(cds)("Rewriting and linking classes: done");
19581959

1959-
if (HeapShared::is_heap_object_archiving_allowed()) {
1960-
// Avoid fragmentation while archiving heap objects.
1961-
Universe::heap()->soft_ref_policy()->set_should_clear_all_soft_refs(true);
1962-
Universe::heap()->collect(GCCause::_archive_time_gc);
1963-
Universe::heap()->soft_ref_policy()->set_should_clear_all_soft_refs(false);
1964-
}
1965-
19661960
VM_PopulateDumpSharedSpace op;
1961+
MutexLocker ml(THREAD, HeapShared::is_heap_object_archiving_allowed() ?
1962+
Heap_lock : NULL); // needed by HeapShared::run_gc()
19671963
VMThread::execute(&op);
19681964
}
19691965
}

‎test/hotspot/jtreg/runtime/cds/appcds/javaldr/GCDuringDump.java

+7-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -41,6 +41,7 @@ public class GCDuringDump {
4141
};
4242
public static String agentClasses[] = {
4343
GCDuringDumpTransformer.class.getName(),
44+
GCDuringDumpTransformer.MyCleaner.class.getName(),
4445
};
4546

4647
public static void main(String[] args) throws Throwable {
@@ -55,15 +56,18 @@ public static void main(String[] args) throws Throwable {
5556
String gcLog = Boolean.getBoolean("test.cds.verbose.gc") ?
5657
"-Xlog:gc*=info,gc+region=trace,gc+alloc+region=debug" : "-showversion";
5758

58-
for (int i=0; i<2; i++) {
59+
for (int i=0; i<3; i++) {
5960
// i = 0 -- run without agent = no extra GCs
6061
// i = 1 -- run with agent = cause extra GCs
62+
// i = 2 -- run with agent = cause extra GCs + use java.lang.ref.Cleaner
6163

6264
String extraArg = (i == 0) ? "-showversion" : "-javaagent:" + agentJar;
6365
String extraOption = (i == 0) ? "-showversion" : "-XX:+AllowArchivingWithJavaAgent";
66+
String extraOption2 = (i != 2) ? "-showversion" : "-Dtest.with.cleaner=true";
6467

6568
TestCommon.testDump(appJar, TestCommon.list(Hello.class.getName()),
66-
"-XX:+UnlockDiagnosticVMOptions", extraOption,
69+
"-XX:+UnlockDiagnosticVMOptions", extraOption, extraOption2,
70+
"-Xlog:exceptions=trace",
6771
extraArg, "-Xmx32m", gcLog);
6872

6973
TestCommon.run(

‎test/hotspot/jtreg/runtime/cds/appcds/javaldr/GCDuringDumpTransformer.java

+41-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -25,18 +25,40 @@
2525
import java.lang.instrument.ClassFileTransformer;
2626
import java.lang.instrument.Instrumentation;
2727
import java.lang.instrument.IllegalClassFormatException;
28+
import java.lang.ref.Cleaner;
2829
import java.security.ProtectionDomain;
2930

3031
public class GCDuringDumpTransformer implements ClassFileTransformer {
32+
static boolean TEST_WITH_CLEANER = Boolean.getBoolean("test.with.cleaner");
33+
static Cleaner cleaner;
34+
static Thread thread;
35+
static Object garbage;
36+
37+
static {
38+
if (TEST_WITH_CLEANER) {
39+
cleaner = Cleaner.create();
40+
garbage = new Object();
41+
cleaner.register(garbage, new MyCleaner());
42+
System.out.println("Registered cleaner");
43+
}
44+
}
45+
3146
public byte[] transform(ClassLoader loader, String name, Class<?> classBeingRedefined,
3247
ProtectionDomain pd, byte[] buffer) throws IllegalClassFormatException {
33-
try {
34-
makeGarbage();
35-
} catch (Throwable t) {
36-
t.printStackTrace();
48+
if (TEST_WITH_CLEANER) {
49+
if (name.equals("Hello")) {
50+
garbage = null;
51+
System.out.println("Unreferenced GCDuringDumpTransformer.garbage");
52+
}
53+
} else {
3754
try {
38-
Thread.sleep(200); // let GC to have a chance to run
39-
} catch (Throwable t2) {}
55+
makeGarbage();
56+
} catch (Throwable t) {
57+
t.printStackTrace();
58+
try {
59+
Thread.sleep(200); // let GC to have a chance to run
60+
} catch (Throwable t2) {}
61+
}
4062
}
4163

4264
return null;
@@ -45,7 +67,7 @@ public byte[] transform(ClassLoader loader, String name, Class<?> classBeingRede
4567
private static Instrumentation savedInstrumentation;
4668

4769
public static void premain(String agentArguments, Instrumentation instrumentation) {
48-
System.out.println("ClassFileTransformer.premain() is called");
70+
System.out.println("ClassFileTransformer.premain() is called: TEST_WITH_CLEANER = " + TEST_WITH_CLEANER);
4971
instrumentation.addTransformer(new GCDuringDumpTransformer(), /*canRetransform=*/true);
5072
savedInstrumentation = instrumentation;
5173
}
@@ -63,4 +85,15 @@ public static void makeGarbage() {
6385
Object[] a = new Object[10000];
6486
}
6587
}
88+
89+
static class MyCleaner implements Runnable {
90+
static int count = 0;
91+
int i = count++;
92+
public void run() {
93+
// Allocate something. This will cause G1 to allocate an EDEN region.
94+
// See JDK-8245925
95+
Object o = new Object();
96+
System.out.println("cleaning " + i);
97+
}
98+
}
6699
}

0 commit comments

Comments
 (0)
Please sign in to comment.