提交 e99ecd16 编写于 作者: E ehelin

8042933: assert(capacity_until_gc >= committed_bytes) failed

Reviewed-by: stefank, jmasa
上级 3da357c1
......@@ -1423,6 +1423,17 @@ size_t MetaspaceGC::dec_capacity_until_GC(size_t v) {
return (size_t)Atomic::add_ptr(-(intptr_t)v, &_capacity_until_GC);
}
void MetaspaceGC::initialize() {
// Set the high-water mark to MaxMetapaceSize during VM initializaton since
// we can't do a GC during initialization.
_capacity_until_GC = MaxMetaspaceSize;
}
void MetaspaceGC::post_initialize() {
// Reset the high-water mark once the VM initialization is done.
_capacity_until_GC = MAX2(MetaspaceAux::committed_bytes(), MetaspaceSize);
}
bool MetaspaceGC::can_expand(size_t word_size, bool is_class) {
// Check if the compressed class space is full.
if (is_class && Metaspace::using_class_space()) {
......@@ -1443,21 +1454,13 @@ bool MetaspaceGC::can_expand(size_t word_size, bool is_class) {
size_t MetaspaceGC::allowed_expansion() {
size_t committed_bytes = MetaspaceAux::committed_bytes();
size_t left_until_max = MaxMetaspaceSize - committed_bytes;
// Always grant expansion if we are initiating the JVM,
// or if the GC_locker is preventing GCs.
if (!is_init_completed() || GC_locker::is_active_and_needs_gc()) {
return left_until_max / BytesPerWord;
}
size_t capacity_until_gc = capacity_until_GC();
if (capacity_until_gc <= committed_bytes) {
return 0;
}
assert(capacity_until_gc >= committed_bytes,
err_msg("capacity_until_gc: " SIZE_FORMAT " < committed_bytes: " SIZE_FORMAT,
capacity_until_gc, committed_bytes));
size_t left_until_max = MaxMetaspaceSize - committed_bytes;
size_t left_until_GC = capacity_until_gc - committed_bytes;
size_t left_to_commit = MIN2(left_until_GC, left_until_max);
......@@ -1469,7 +1472,15 @@ void MetaspaceGC::compute_new_size() {
uint current_shrink_factor = _shrink_factor;
_shrink_factor = 0;
const size_t used_after_gc = MetaspaceAux::capacity_bytes();
// Using committed_bytes() for used_after_gc is an overestimation, since the
// chunk free lists are included in committed_bytes() and the memory in an
// un-fragmented chunk free list is available for future allocations.
// However, if the chunk free lists becomes fragmented, then the memory may
// not be available for future allocations and the memory is therefore "in use".
// Including the chunk free lists in the definition of "in use" is therefore
// necessary. Not including the chunk free lists can cause capacity_until_GC to
// shrink below committed_bytes() and this has caused serious bugs in the past.
const size_t used_after_gc = MetaspaceAux::committed_bytes();
const size_t capacity_until_GC = MetaspaceGC::capacity_until_GC();
const double minimum_free_percentage = MinMetaspaceFreeRatio / 100.0;
......@@ -3093,6 +3104,8 @@ void Metaspace::ergo_initialize() {
}
void Metaspace::global_initialize() {
MetaspaceGC::initialize();
// Initialize the alignment for shared spaces.
int max_alignment = os::vm_page_size();
size_t cds_total = 0;
......@@ -3200,10 +3213,13 @@ void Metaspace::global_initialize() {
}
}
MetaspaceGC::initialize();
_tracer = new MetaspaceTracer();
}
void Metaspace::post_initialize() {
MetaspaceGC::post_initialize();
}
Metachunk* Metaspace::get_initialization_chunk(MetadataType mdtype,
size_t chunk_word_size,
size_t chunk_bunch) {
......
......@@ -208,6 +208,7 @@ class Metaspace : public CHeapObj<mtClass> {
static void ergo_initialize();
static void global_initialize();
static void post_initialize();
static size_t first_chunk_word_size() { return _first_chunk_word_size; }
static size_t first_class_chunk_word_size() { return _first_class_chunk_word_size; }
......@@ -398,7 +399,8 @@ class MetaspaceGC : AllStatic {
public:
static void initialize() { _capacity_until_GC = MetaspaceSize; }
static void initialize();
static void post_initialize();
static size_t capacity_until_GC();
static size_t inc_capacity_until_GC(size_t v);
......
......@@ -3574,6 +3574,8 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) {
// debug stuff, that does not work until all basic classes have been initialized.
set_init_completed();
Metaspace::post_initialize();
#ifndef USDT2
HS_DTRACE_PROBE(hotspot, vm__init__end);
#else /* USDT2 */
......
/*
* Copyright (c) 2013, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.util.ArrayList;
/* @test TestMetaspaceInitialization
* @bug 8042933
* @summary Tests to initialize metaspace with a very low MetaspaceSize
* @library /testlibrary
* @run main/othervm -XX:MetaspaceSize=2m TestMetaspaceInitialization
*/
public class TestMetaspaceInitialization {
private class Internal {
public int x;
public Internal(int x) {
this.x = x;
}
}
private void test() {
ArrayList<Internal> l = new ArrayList<>();
l.add(new Internal(17));
}
public static void main(String[] args) {
new TestMetaspaceInitialization().test();
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册