8042933: assert(capacity_until_gc >= committed_bytes) failed

Fri, 13 Jun 2014 08:44:11 +0200

author
ehelin
date
Fri, 13 Jun 2014 08:44:11 +0200
changeset 6722
e204777ac770
parent 6721
ad51f24671c2
child 6724
6c06bce8d5bd
child 6725
e5d5e7922283

8042933: assert(capacity_until_gc >= committed_bytes) failed
Reviewed-by: stefank, jmasa

src/share/vm/memory/metaspace.cpp file | annotate | diff | comparison | revisions
src/share/vm/memory/metaspace.hpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/thread.cpp file | annotate | diff | comparison | revisions
test/gc/metaspace/TestMetaspaceInitialization.java file | annotate | diff | comparison | revisions
     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 +}

mercurial