--- old/src/hotspot/share/memory/metaspace.cpp 2019-01-31 23:10:16.486519402 +0900 +++ new/src/hotspot/share/memory/metaspace.cpp 2019-01-31 23:10:16.137531030 +0900 @@ -132,7 +132,13 @@ return value; } -bool MetaspaceGC::inc_capacity_until_GC(size_t v, size_t* new_cap_until_GC, size_t* old_cap_until_GC) { +// Try to increase metaspace size by v bytes. Returns true if +// succeeded, false if not due to competing threads trying. +// Optionally returns new and old metaspace capacity in +// new_cap_until_GC and old_cap_until_GC respectively. +// Optionally sets can_retry to indicate whether if there is actually +// enough space remaining to satisfy the request. +bool MetaspaceGC::inc_capacity_until_GC(size_t v, size_t* new_cap_until_GC, size_t* old_cap_until_GC, bool* can_retry) { assert_is_aligned(v, Metaspace::commit_alignment()); size_t old_capacity_until_GC = _capacity_until_GC; @@ -143,6 +149,16 @@ new_value = align_down(max_uintx, Metaspace::commit_alignment()); } + if (new_value > MaxMetaspaceSize) { + if (can_retry != NULL) { + *can_retry = false; + } + return false; + } + + if (can_retry != NULL) { + *can_retry = true; + } size_t prev_value = Atomic::cmpxchg(new_value, &_capacity_until_GC, old_capacity_until_GC); if (old_capacity_until_GC != prev_value) { @@ -236,7 +252,7 @@ const double min_tmp = used_after_gc / maximum_used_percentage; size_t minimum_desired_capacity = - (size_t)MIN2(min_tmp, double(max_uintx)); + (size_t)MIN2(min_tmp, double(MaxMetaspaceSize)); // Don't shrink less than the initial generation size minimum_desired_capacity = MAX2(minimum_desired_capacity, MetaspaceSize); @@ -283,7 +299,7 @@ const double maximum_free_percentage = MaxMetaspaceFreeRatio / 100.0; const double minimum_used_percentage = 1.0 - maximum_free_percentage; const double max_tmp = used_after_gc / minimum_used_percentage; - size_t maximum_desired_capacity = (size_t)MIN2(max_tmp, double(max_uintx)); + size_t maximum_desired_capacity = (size_t)MIN2(max_tmp, double(MaxMetaspaceSize)); maximum_desired_capacity = MAX2(maximum_desired_capacity, MetaspaceSize); log_trace(gc, metaspace)(" maximum_free_percentage: %6.2f minimum_used_percentage: %6.2f", @@ -1470,6 +1486,7 @@ size_t before = 0; size_t after = 0; + bool can_retry = true; MetaWord* res; bool incremented; @@ -1477,9 +1494,9 @@ // the HWM, an allocation is still attempted. This is because another thread must then // have incremented the HWM and therefore the allocation might still succeed. do { - incremented = MetaspaceGC::inc_capacity_until_GC(delta_bytes, &after, &before); + incremented = MetaspaceGC::inc_capacity_until_GC(delta_bytes, &after, &before, &can_retry); res = allocate(word_size, mdtype); - } while (!incremented && res == NULL); + } while (!incremented && res == NULL && can_retry); if (incremented) { Metaspace::tracer()->report_gc_threshold(before, after, --- old/src/hotspot/share/memory/metaspace.hpp 2019-01-31 23:10:17.261493579 +0900 +++ new/src/hotspot/share/memory/metaspace.hpp 2019-01-31 23:10:16.914505141 +0900 @@ -457,7 +457,8 @@ static size_t capacity_until_GC(); static bool inc_capacity_until_GC(size_t v, size_t* new_cap_until_GC = NULL, - size_t* old_cap_until_GC = NULL); + size_t* old_cap_until_GC = NULL, + bool* can_retry = NULL); static size_t dec_capacity_until_GC(size_t v); static bool should_concurrent_collect() { return _should_concurrent_collect; } --- old/test/hotspot/jtreg/vmTestbase/metaspace/shrink_grow/ShrinkGrowTest/ShrinkGrowTest.java 2019-01-31 23:10:17.994469157 +0900 +++ new/test/hotspot/jtreg/vmTestbase/metaspace/shrink_grow/ShrinkGrowTest/ShrinkGrowTest.java 2019-01-31 23:10:17.648480685 +0900 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ /* * @test * + * @bug 8217432 * @summary converted from VM Testbase metaspace/shrink_grow/ShrinkGrowTest. * * @requires vm.opt.final.ClassUnloading