8268458: Add verification type for evacuation failures
Reviewed-by: kbarrett, iwalulya
This commit is contained in:
parent
a58c477c49
commit
cd20c01942
@ -93,6 +93,8 @@ void G1Arguments::parse_verification_type(const char* type) {
|
||||
G1HeapVerifier::enable_verification_type(G1HeapVerifier::G1VerifyConcurrentStart);
|
||||
} else if (strcmp(type, "mixed") == 0) {
|
||||
G1HeapVerifier::enable_verification_type(G1HeapVerifier::G1VerifyMixed);
|
||||
} else if (strcmp(type, "young-evac-fail") == 0) {
|
||||
G1HeapVerifier::enable_verification_type(G1HeapVerifier::G1VerifyYoungEvacFail);
|
||||
} else if (strcmp(type, "remark") == 0) {
|
||||
G1HeapVerifier::enable_verification_type(G1HeapVerifier::G1VerifyRemark);
|
||||
} else if (strcmp(type, "cleanup") == 0) {
|
||||
@ -101,7 +103,7 @@ void G1Arguments::parse_verification_type(const char* type) {
|
||||
G1HeapVerifier::enable_verification_type(G1HeapVerifier::G1VerifyFull);
|
||||
} else {
|
||||
log_warning(gc, verify)("VerifyGCType: '%s' is unknown. Available types are: "
|
||||
"young-normal, concurrent-start, mixed, remark, cleanup and full", type);
|
||||
"young-normal, young-evac-fail, concurrent-start, mixed, remark, cleanup and full", type);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2851,6 +2851,9 @@ void G1CollectedHeap::verify_before_young_collection(G1HeapVerifier::G1VerifyTyp
|
||||
}
|
||||
|
||||
void G1CollectedHeap::verify_after_young_collection(G1HeapVerifier::G1VerifyType type) {
|
||||
if (evacuation_failed()) {
|
||||
type = (G1HeapVerifier::G1VerifyType)(type | G1HeapVerifier::G1VerifyYoungEvacFail);
|
||||
}
|
||||
if (VerifyRememberedSets) {
|
||||
log_info(gc, verify)("[Verifying RemSets after GC]");
|
||||
VerifyRegionRemSetClosure v_cl;
|
||||
|
@ -467,7 +467,7 @@ void G1HeapVerifier::enable_verification_type(G1VerifyType type) {
|
||||
}
|
||||
|
||||
bool G1HeapVerifier::should_verify(G1VerifyType type) {
|
||||
return (_enabled_verification_types & type) == type;
|
||||
return (_enabled_verification_types & type) != 0;
|
||||
}
|
||||
|
||||
void G1HeapVerifier::verify(VerifyOption vo) {
|
||||
|
@ -45,9 +45,10 @@ public:
|
||||
G1VerifyYoungNormal = 1, // -XX:VerifyGCType=young-normal
|
||||
G1VerifyConcurrentStart = 2, // -XX:VerifyGCType=concurrent-start
|
||||
G1VerifyMixed = 4, // -XX:VerifyGCType=mixed
|
||||
G1VerifyRemark = 8, // -XX:VerifyGCType=remark
|
||||
G1VerifyCleanup = 16, // -XX:VerifyGCType=cleanup
|
||||
G1VerifyFull = 32, // -XX:VerifyGCType=full
|
||||
G1VerifyYoungEvacFail = 8, // -XX:VerifyGCType=young-evac-fail
|
||||
G1VerifyRemark = 16, // -XX:VerifyGCType=remark
|
||||
G1VerifyCleanup = 32, // -XX:VerifyGCType=cleanup
|
||||
G1VerifyFull = 64, // -XX:VerifyGCType=full
|
||||
G1VerifyAll = -1
|
||||
};
|
||||
|
||||
|
@ -41,20 +41,20 @@ TEST_VM_F(G1HeapVerifierTest, parse) {
|
||||
LogConfiguration::configure_stdout(LogLevel::Off, true, LOG_TAGS(gc, verify));
|
||||
|
||||
// Default is to verify everything.
|
||||
ASSERT_TRUE(G1HeapVerifier::should_verify(G1HeapVerifier::G1VerifyAll));
|
||||
ASSERT_TRUE(G1HeapVerifier::should_verify(G1HeapVerifier::G1VerifyYoungNormal));
|
||||
ASSERT_TRUE(G1HeapVerifier::should_verify(G1HeapVerifier::G1VerifyConcurrentStart));
|
||||
ASSERT_TRUE(G1HeapVerifier::should_verify(G1HeapVerifier::G1VerifyMixed));
|
||||
ASSERT_TRUE(G1HeapVerifier::should_verify(G1HeapVerifier::G1VerifyYoungEvacFail));
|
||||
ASSERT_TRUE(G1HeapVerifier::should_verify(G1HeapVerifier::G1VerifyRemark));
|
||||
ASSERT_TRUE(G1HeapVerifier::should_verify(G1HeapVerifier::G1VerifyCleanup));
|
||||
ASSERT_TRUE(G1HeapVerifier::should_verify(G1HeapVerifier::G1VerifyFull));
|
||||
|
||||
// Setting one will disable all other.
|
||||
G1HeapVerifierTest::parse_verification_type("full");
|
||||
ASSERT_FALSE(G1HeapVerifier::should_verify(G1HeapVerifier::G1VerifyAll));
|
||||
ASSERT_FALSE(G1HeapVerifier::should_verify(G1HeapVerifier::G1VerifyYoungNormal));
|
||||
ASSERT_FALSE(G1HeapVerifier::should_verify(G1HeapVerifier::G1VerifyConcurrentStart));
|
||||
ASSERT_FALSE(G1HeapVerifier::should_verify(G1HeapVerifier::G1VerifyMixed));
|
||||
ASSERT_FALSE(G1HeapVerifier::should_verify(G1HeapVerifier::G1VerifyYoungEvacFail));
|
||||
ASSERT_FALSE(G1HeapVerifier::should_verify(G1HeapVerifier::G1VerifyRemark));
|
||||
ASSERT_FALSE(G1HeapVerifier::should_verify(G1HeapVerifier::G1VerifyCleanup));
|
||||
ASSERT_TRUE(G1HeapVerifier::should_verify(G1HeapVerifier::G1VerifyFull));
|
||||
@ -79,7 +79,4 @@ TEST_VM_F(G1HeapVerifierTest, parse) {
|
||||
G1HeapVerifierTest::parse_verification_type("cleanup");
|
||||
ASSERT_TRUE(G1HeapVerifier::should_verify(G1HeapVerifier::G1VerifyRemark));
|
||||
ASSERT_TRUE(G1HeapVerifier::should_verify(G1HeapVerifier::G1VerifyCleanup));
|
||||
|
||||
// Enabling all is not the same as G1VerifyAll
|
||||
ASSERT_FALSE(G1HeapVerifier::should_verify(G1HeapVerifier::G1VerifyAll));
|
||||
}
|
||||
|
@ -37,6 +37,7 @@ import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
||||
import jdk.test.lib.Asserts;
|
||||
import jdk.test.lib.Platform;
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
import sun.hotspot.WhiteBox;
|
||||
@ -52,6 +53,9 @@ public class TestVerifyGCType {
|
||||
testAllExplicitlyEnabled();
|
||||
testFullAndRemark();
|
||||
testConcurrentMark();
|
||||
if (Platform.isDebugBuild()) {
|
||||
testYoungEvacFail();
|
||||
}
|
||||
testBadVerificationType();
|
||||
}
|
||||
|
||||
@ -115,13 +119,33 @@ public class TestVerifyGCType {
|
||||
verifyCollection("Pause Full", false, false, false, output.getStdout());
|
||||
}
|
||||
|
||||
private static void testYoungEvacFail() throws Exception {
|
||||
OutputAnalyzer output;
|
||||
output = testWithVerificationType(new String[] {"young-evac-fail"},
|
||||
new String[] {"-XX:+G1EvacuationFailureALot",
|
||||
"-XX:G1EvacuationFailureALotCount=100",
|
||||
"-XX:G1EvacuationFailureALotInterval=1",
|
||||
"-XX:+UnlockDiagnosticVMOptions",
|
||||
"-XX:-G1AllowPreventiveGC"});
|
||||
output.shouldHaveExitValue(0);
|
||||
|
||||
verifyCollection("Pause Young (Normal)", false, false, true, output.getStdout());
|
||||
verifyCollection("Pause Young (Concurrent Start)", false, false, true, output.getStdout());
|
||||
verifyCollection("Pause Young (Mixed)", false, false, true, output.getStdout());
|
||||
verifyCollection("Pause Young (Prepare Mixed)", false, false, true, output.getStdout());
|
||||
verifyCollection("Pause Remark", false, false, false, output.getStdout());
|
||||
verifyCollection("Pause Cleanup", false, false, false, output.getStdout());
|
||||
verifyCollection("Pause Full", false, false, false, output.getStdout());
|
||||
}
|
||||
|
||||
|
||||
private static void testBadVerificationType() throws Exception {
|
||||
OutputAnalyzer output;
|
||||
// Test bad type
|
||||
output = testWithVerificationType(new String[] {"old"});
|
||||
output.shouldHaveExitValue(0);
|
||||
|
||||
output.shouldMatch("VerifyGCType: '.*' is unknown. Available types are: young-normal, concurrent-start, mixed, remark, cleanup and full");
|
||||
output.shouldMatch("VerifyGCType: '.*' is unknown. Available types are: young-normal, young-evac-fail, concurrent-start, mixed, remark, cleanup and full");
|
||||
verifyCollection("Pause Young (Normal)", true, false, true, output.getStdout());
|
||||
verifyCollection("Pause Young (Concurrent Start)", true, false, true, output.getStdout());
|
||||
verifyCollection("Pause Young (Mixed)", true, false, true, output.getStdout());
|
||||
@ -131,7 +155,7 @@ public class TestVerifyGCType {
|
||||
verifyCollection("Pause Full", true, true, true, output.getStdout());
|
||||
}
|
||||
|
||||
private static OutputAnalyzer testWithVerificationType(String[] types) throws Exception {
|
||||
private static OutputAnalyzer testWithVerificationType(String[] types, String... extraOpts) throws Exception {
|
||||
ArrayList<String> basicOpts = new ArrayList<>();
|
||||
Collections.addAll(basicOpts, new String[] {
|
||||
"-Xbootclasspath/a:.",
|
||||
@ -151,10 +175,13 @@ public class TestVerifyGCType {
|
||||
basicOpts.add("-XX:VerifyGCType="+verifyType);
|
||||
}
|
||||
|
||||
Collections.addAll(basicOpts, extraOpts);
|
||||
|
||||
basicOpts.add(TriggerGCs.class.getName());
|
||||
|
||||
ProcessBuilder procBuilder = ProcessTools.createJavaProcessBuilder(basicOpts);
|
||||
OutputAnalyzer analyzer = new OutputAnalyzer(procBuilder.start());
|
||||
|
||||
return analyzer;
|
||||
}
|
||||
|
||||
@ -228,6 +255,9 @@ public class TestVerifyGCType {
|
||||
}
|
||||
|
||||
public static class TriggerGCs {
|
||||
|
||||
// This class triggers GCs; we need to make sure that in all of the young gcs
|
||||
// at least some objects survive so that evacuation failure can happen.
|
||||
public static void main(String args[]) throws Exception {
|
||||
WhiteBox wb = WhiteBox.getWhiteBox();
|
||||
// Allocate some memory that can be turned into garbage.
|
||||
@ -241,7 +271,10 @@ public class TestVerifyGCType {
|
||||
// Memory have been promoted to old by full GC. Free
|
||||
// some memory to be reclaimed by concurrent cycle.
|
||||
partialFree(used);
|
||||
|
||||
used = alloc1M();
|
||||
wb.g1StartConcMarkCycle(); // concurrent-start, remark and cleanup
|
||||
partialFree(used);
|
||||
|
||||
// Sleep to make sure concurrent cycle is done
|
||||
while (wb.g1InConcurrentMark()) {
|
||||
@ -249,8 +282,13 @@ public class TestVerifyGCType {
|
||||
}
|
||||
|
||||
// Trigger two young GCs, first will be young-prepare-mixed, second will be mixed.
|
||||
used = alloc1M();
|
||||
wb.youngGC(); // young-prepare-mixed
|
||||
partialFree(used);
|
||||
|
||||
used = alloc1M();
|
||||
wb.youngGC(); // mixed
|
||||
partialFree(used);
|
||||
}
|
||||
|
||||
private static Object[] alloc1M() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user