/* * Copyright (c) 2021, 2022 SAP SE. All rights reserved. * Copyright (c) 2021, 2022, 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.
*/
// convenience log. switch on if debugging tests. Don't use tty, plain stdio only. //#define LOG(...) { printf(__VA_ARGS__); printf("\n"); fflush(stdout); } #define LOG(...)
// This tests the ability of the NMT pre-init system to deal with various combinations // of pre- and post-init-allocations.
// The tests consist of two phases: // 1) before NMT initialization (pre-NMT-init) we allocate and reallocate a bunch of // blocks via os::malloc() and os::realloc(), and free some of them via os::free() // 2) after NMT initialization, we reallocate some more, then free all of them. // // The intent is to check that blocks allocated in pre-init phase and potentially realloced // in pre-init phase are handled correctly if further realloc'ed or free'd post-init.
// We manage to run tests in different phases with this technique: // - for the pre-init phase, we start the tests in the constructor of a global object; that constructor will // run as part of the dyn. C++ initialization of the gtestlauncher binary. Since the gtestlauncher links // *statically* against the libjvm, gtestlauncher and libjvm initialization fold into one and are the same. // - for the post-init phase, we just start it inside a TEST_VM scope, which needs to create the VM for // us. So inside that scope VM initialization ran and with it the NMT initialization. // To be sure, we assert those assumptions.
// Some shorts to save writing out the flags every time staticvoid* os_malloc(size_t s) { return os::malloc(s, mtTest); } staticvoid* os_realloc(void* old, size_t s) { return os::realloc(old, s, mtTest); }
staticvoid log_state() { // Don't use tty! the only safe thing to use at all times is stringStream. char tmp[256];
stringStream ss(tmp, sizeof(tmp));
NMTPreInit::print_state(&ss);
LOG("%s", tmp);
}
class TestAllocations { void* p1, *p2, *p3, *p4; public:
TestAllocations() {
test_pre();
} void test_pre() { // Note that this part will run every time a gtestlauncher execs (so, for every TEST_OTHER_VM).
assert(!MemTracker::is_initialized(), "This should be run in pre-init phase (as part of C++ dyn. initialization)");
LOG("corner cases, pre-init (%d)", os::current_process_id());
log_state();
p1 = os_malloc(100); // normal allocation
os::free(os_malloc(0)); // 0-sized allocation, should be free-able
p2 = os_realloc(os_malloc(10), 20); // realloc, growing
p3 = os_realloc(os_malloc(20), 10); // realloc, shrinking
p4 = os_realloc(NULL, 10); // realloc with NULL pointer
os_realloc(os_realloc(os_malloc(20), 0), 30); // realloc to size 0 and back up again
os::free(os_malloc(20)); // malloc, free
os::free(os_realloc(os_malloc(20), 30)); // malloc, realloc, free
os::free(NULL); // free(null)
DEBUG_ONLY(NMTPreInit::verify();)
// This should result in a fatal native oom error from NMT preinit with a clear error message. // It should not result in a SEGV or anything similar. Unfortunately difficult to test // automatically. // Uncomment to test manually.
// case 1: overflow // os_malloc(SIZE_MAX);
// case 2: failing malloc // os_malloc(SIZE_MAX - M);
// case 3: overflow in realloc // void* p = os_malloc(10); // p = os_realloc(p, SIZE_MAX);
// case 4: failing realloc // void* p = os_malloc(10); // p = os_realloc(p, SIZE_MAX - M);
log_state();
} void test_post() {
assert(MemTracker::is_initialized(), "This should be run in post-init phase (from inside a TEST_VM test)");
LOG("corner cases, post-init (%d)", os::current_process_id());
log_state();
p1 = os_realloc(p1, 140); // realloc from pre-init-phase, growing
p2 = os_realloc(p2, 150); // realloc from pre-init-phase, growing
p3 = os_realloc(p3, 50); // realloc from pre-init-phase, growing
p4 = os_realloc(p4, 8); // realloc from pre-init-phase, shrinking
DEBUG_ONLY(NMTPreInit::verify();)
log_state();
} void free_all() {
assert(MemTracker::is_initialized(), "This should be run in post-init phase (from inside a TEST_VM test)");
LOG("corner cases, free-all (%d)", os::current_process_id());
log_state();
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.