Fri, 13 Jun 2014 08:44:11 +0200
8042933: assert(capacity_until_gc >= committed_bytes) failed
Reviewed-by: stefank, jmasa
1.1 --- a/src/share/vm/memory/metaspace.cpp Mon Jun 09 15:42:31 2014 -0700 1.2 +++ b/src/share/vm/memory/metaspace.cpp Fri Jun 13 08:44:11 2014 +0200 1.3 @@ -1423,6 +1423,17 @@ 1.4 return (size_t)Atomic::add_ptr(-(intptr_t)v, &_capacity_until_GC); 1.5 } 1.6 1.7 +void MetaspaceGC::initialize() { 1.8 + // Set the high-water mark to MaxMetapaceSize during VM initializaton since 1.9 + // we can't do a GC during initialization. 1.10 + _capacity_until_GC = MaxMetaspaceSize; 1.11 +} 1.12 + 1.13 +void MetaspaceGC::post_initialize() { 1.14 + // Reset the high-water mark once the VM initialization is done. 1.15 + _capacity_until_GC = MAX2(MetaspaceAux::committed_bytes(), MetaspaceSize); 1.16 +} 1.17 + 1.18 bool MetaspaceGC::can_expand(size_t word_size, bool is_class) { 1.19 // Check if the compressed class space is full. 1.20 if (is_class && Metaspace::using_class_space()) { 1.21 @@ -1443,21 +1454,13 @@ 1.22 1.23 size_t MetaspaceGC::allowed_expansion() { 1.24 size_t committed_bytes = MetaspaceAux::committed_bytes(); 1.25 + size_t capacity_until_gc = capacity_until_GC(); 1.26 + 1.27 + assert(capacity_until_gc >= committed_bytes, 1.28 + err_msg("capacity_until_gc: " SIZE_FORMAT " < committed_bytes: " SIZE_FORMAT, 1.29 + capacity_until_gc, committed_bytes)); 1.30 1.31 size_t left_until_max = MaxMetaspaceSize - committed_bytes; 1.32 - 1.33 - // Always grant expansion if we are initiating the JVM, 1.34 - // or if the GC_locker is preventing GCs. 1.35 - if (!is_init_completed() || GC_locker::is_active_and_needs_gc()) { 1.36 - return left_until_max / BytesPerWord; 1.37 - } 1.38 - 1.39 - size_t capacity_until_gc = capacity_until_GC(); 1.40 - 1.41 - if (capacity_until_gc <= committed_bytes) { 1.42 - return 0; 1.43 - } 1.44 - 1.45 size_t left_until_GC = capacity_until_gc - committed_bytes; 1.46 size_t left_to_commit = MIN2(left_until_GC, left_until_max); 1.47 1.48 @@ -1469,7 +1472,15 @@ 1.49 uint current_shrink_factor = _shrink_factor; 1.50 _shrink_factor = 0; 1.51 1.52 - const size_t used_after_gc = MetaspaceAux::capacity_bytes(); 1.53 + // Using committed_bytes() for used_after_gc is an overestimation, since the 1.54 + // chunk free lists are included in committed_bytes() and the memory in an 1.55 + // un-fragmented chunk free list is available for future allocations. 1.56 + // However, if the chunk free lists becomes fragmented, then the memory may 1.57 + // not be available for future allocations and the memory is therefore "in use". 1.58 + // Including the chunk free lists in the definition of "in use" is therefore 1.59 + // necessary. Not including the chunk free lists can cause capacity_until_GC to 1.60 + // shrink below committed_bytes() and this has caused serious bugs in the past. 1.61 + const size_t used_after_gc = MetaspaceAux::committed_bytes(); 1.62 const size_t capacity_until_GC = MetaspaceGC::capacity_until_GC(); 1.63 1.64 const double minimum_free_percentage = MinMetaspaceFreeRatio / 100.0; 1.65 @@ -3093,6 +3104,8 @@ 1.66 } 1.67 1.68 void Metaspace::global_initialize() { 1.69 + MetaspaceGC::initialize(); 1.70 + 1.71 // Initialize the alignment for shared spaces. 1.72 int max_alignment = os::vm_page_size(); 1.73 size_t cds_total = 0; 1.74 @@ -3200,10 +3213,13 @@ 1.75 } 1.76 } 1.77 1.78 - MetaspaceGC::initialize(); 1.79 _tracer = new MetaspaceTracer(); 1.80 } 1.81 1.82 +void Metaspace::post_initialize() { 1.83 + MetaspaceGC::post_initialize(); 1.84 +} 1.85 + 1.86 Metachunk* Metaspace::get_initialization_chunk(MetadataType mdtype, 1.87 size_t chunk_word_size, 1.88 size_t chunk_bunch) {
2.1 --- a/src/share/vm/memory/metaspace.hpp Mon Jun 09 15:42:31 2014 -0700 2.2 +++ b/src/share/vm/memory/metaspace.hpp Fri Jun 13 08:44:11 2014 +0200 2.3 @@ -208,6 +208,7 @@ 2.4 2.5 static void ergo_initialize(); 2.6 static void global_initialize(); 2.7 + static void post_initialize(); 2.8 2.9 static size_t first_chunk_word_size() { return _first_chunk_word_size; } 2.10 static size_t first_class_chunk_word_size() { return _first_class_chunk_word_size; } 2.11 @@ -398,7 +399,8 @@ 2.12 2.13 public: 2.14 2.15 - static void initialize() { _capacity_until_GC = MetaspaceSize; } 2.16 + static void initialize(); 2.17 + static void post_initialize(); 2.18 2.19 static size_t capacity_until_GC(); 2.20 static size_t inc_capacity_until_GC(size_t v);
3.1 --- a/src/share/vm/runtime/thread.cpp Mon Jun 09 15:42:31 2014 -0700 3.2 +++ b/src/share/vm/runtime/thread.cpp Fri Jun 13 08:44:11 2014 +0200 3.3 @@ -3574,6 +3574,8 @@ 3.4 // debug stuff, that does not work until all basic classes have been initialized. 3.5 set_init_completed(); 3.6 3.7 + Metaspace::post_initialize(); 3.8 + 3.9 #ifndef USDT2 3.10 HS_DTRACE_PROBE(hotspot, vm__init__end); 3.11 #else /* USDT2 */
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/test/gc/metaspace/TestMetaspaceInitialization.java Fri Jun 13 08:44:11 2014 +0200 4.3 @@ -0,0 +1,48 @@ 4.4 +/* 4.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 4.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4.7 + * 4.8 + * This code is free software; you can redistribute it and/or modify it 4.9 + * under the terms of the GNU General Public License version 2 only, as 4.10 + * published by the Free Software Foundation. 4.11 + * 4.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 4.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 4.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 4.15 + * version 2 for more details (a copy is included in the LICENSE file that 4.16 + * accompanied this code). 4.17 + * 4.18 + * You should have received a copy of the GNU General Public License version 4.19 + * 2 along with this work; if not, write to the Free Software Foundation, 4.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 4.21 + * 4.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 4.23 + * or visit www.oracle.com if you need additional information or have any 4.24 + * questions. 4.25 + */ 4.26 + 4.27 +import java.util.ArrayList; 4.28 + 4.29 +/* @test TestMetaspaceInitialization 4.30 + * @bug 8042933 4.31 + * @summary Tests to initialize metaspace with a very low MetaspaceSize 4.32 + * @library /testlibrary 4.33 + * @run main/othervm -XX:MetaspaceSize=2m TestMetaspaceInitialization 4.34 + */ 4.35 +public class TestMetaspaceInitialization { 4.36 + private class Internal { 4.37 + public int x; 4.38 + public Internal(int x) { 4.39 + this.x = x; 4.40 + } 4.41 + } 4.42 + 4.43 + private void test() { 4.44 + ArrayList<Internal> l = new ArrayList<>(); 4.45 + l.add(new Internal(17)); 4.46 + } 4.47 + 4.48 + public static void main(String[] args) { 4.49 + new TestMetaspaceInitialization().test(); 4.50 + } 4.51 +}