From b5a7426996bb0e36319186756c46cfa7d0ab6e64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Sj=C3=B6len?= Date: Mon, 20 Feb 2023 14:23:54 +0000 Subject: [PATCH] 8301749: Tracking malloc pooled memory size Reviewed-by: dholmes, stuefe --- src/hotspot/os/linux/mallocInfoDcmd.cpp | 62 +++++++++++++++++++ src/hotspot/os/linux/mallocInfoDcmd.hpp | 51 +++++++++++++++ src/hotspot/os/linux/os_linux.cpp | 11 ++++ src/hotspot/os/linux/os_linux.hpp | 4 ++ .../share/services/diagnosticCommand.cpp | 2 + src/jdk.jcmd/share/man/jcmd.1 | 9 +++ .../dcmd/vm/MallocInfoTest.java | 57 +++++++++++++++++ 7 files changed, 196 insertions(+) create mode 100644 src/hotspot/os/linux/mallocInfoDcmd.cpp create mode 100644 src/hotspot/os/linux/mallocInfoDcmd.hpp create mode 100644 test/hotspot/jtreg/serviceability/dcmd/vm/MallocInfoTest.java diff --git a/src/hotspot/os/linux/mallocInfoDcmd.cpp b/src/hotspot/os/linux/mallocInfoDcmd.cpp new file mode 100644 index 00000000000..9fd35e6fe6d --- /dev/null +++ b/src/hotspot/os/linux/mallocInfoDcmd.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2023, 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. + * + */ + +#include "precompiled.hpp" +#include "mallocInfoDcmd.hpp" +#include "os_linux.hpp" +#include "utilities/globalDefinitions.hpp" +#include "utilities/ostream.hpp" + +#include + +constexpr const char* malloc_info_unavailable = "Error: malloc_info(3) not available."; + +void MallocInfoDcmd::execute(DCmdSource source, TRAPS) { +#ifdef __GLIBC__ + char* buf; + size_t size; + ALLOW_C_FUNCTION(::open_memstream, FILE* stream = ::open_memstream(&buf, &size);) + if (stream == nullptr) { + _output->print_cr("Error: Could not call malloc_info(3)"); + return; + } + + int err = os::Linux::malloc_info(stream); + if (err == 0) { + ALLOW_C_FUNCTION(::fflush, fflush(stream);) + _output->print_raw(buf); + _output->cr(); + } else if (err == -1) { + _output->print_cr("Error: %s", os::strerror(errno)); + } else if (err == -2) { + _output->print_cr(malloc_info_unavailable); + } else { + ShouldNotReachHere(); + } + ALLOW_C_FUNCTION(::fclose, ::fclose(stream);) + ALLOW_C_FUNCTION(::free, ::free(buf);) +#else + _output->print_cr(malloc_info_unavailable); +#endif // __GLIBC__ +} diff --git a/src/hotspot/os/linux/mallocInfoDcmd.hpp b/src/hotspot/os/linux/mallocInfoDcmd.hpp new file mode 100644 index 00000000000..9f52d83fba3 --- /dev/null +++ b/src/hotspot/os/linux/mallocInfoDcmd.hpp @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2023, 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. + * + */ + +#ifndef OS_LINUX_MALLOCINFODCMD_HPP +#define OS_LINUX_MALLOCINFODCMD_HPP + +#include "services/diagnosticCommand.hpp" + +class outputStream; + +class MallocInfoDcmd : public DCmd { +public: + MallocInfoDcmd(outputStream* output, bool heap) : DCmd(output, heap) {} + static const char* name() { + return "System.native_heap_info"; + } + static const char* description() { + return "Attempts to output information regarding native heap usage through malloc_info(3). If unsuccessful outputs \"Error: \" and a reason."; + } + static const char* impact() { + return "Low"; + } + static const JavaPermission permission() { + JavaPermission p = { "java.lang.management.ManagementPermission", "monitor", nullptr }; + return p; + } + void execute(DCmdSource source, TRAPS) override; +}; + +#endif // OS_LINUX_MALLOCINFODCMD_HPP diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp index 864c7c3a411..42680218d8b 100644 --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp @@ -200,6 +200,9 @@ struct new_mallinfo { }; typedef struct new_mallinfo (*mallinfo2_func_t)(void); static mallinfo2_func_t g_mallinfo2 = nullptr; + +typedef int (*malloc_info_func_t)(int options, FILE *stream); +static malloc_info_func_t g_malloc_info = nullptr; #endif // __GLIBC__ static int clock_tics_per_sec = 100; @@ -4297,6 +4300,7 @@ void os::init(void) { #ifdef __GLIBC__ g_mallinfo = CAST_TO_FN_PTR(mallinfo_func_t, dlsym(RTLD_DEFAULT, "mallinfo")); g_mallinfo2 = CAST_TO_FN_PTR(mallinfo2_func_t, dlsym(RTLD_DEFAULT, "mallinfo2")); + g_malloc_info = CAST_TO_FN_PTR(malloc_info_func_t, dlsym(RTLD_DEFAULT, "malloc_info")); #endif // __GLIBC__ os::Linux::CPUPerfTicks pticks; @@ -5388,6 +5392,13 @@ void os::Linux::get_mallinfo(glibc_mallinfo* out, bool* might_have_wrapped) { ShouldNotReachHere(); } } + +int os::Linux::malloc_info(FILE* stream) { + if (g_malloc_info == nullptr) { + return -2; + } + return g_malloc_info(0, stream); +} #endif // __GLIBC__ bool os::trim_native_heap(os::size_change_t* rss_change) { diff --git a/src/hotspot/os/linux/os_linux.hpp b/src/hotspot/os/linux/os_linux.hpp index 045fca04c44..20639e4031f 100644 --- a/src/hotspot/os/linux/os_linux.hpp +++ b/src/hotspot/os/linux/os_linux.hpp @@ -424,6 +424,10 @@ class os::Linux { size_t keepcost; }; static void get_mallinfo(glibc_mallinfo* out, bool* might_have_wrapped); + + // Calls out to GNU extension malloc_info if available + // otherwise does nothing and returns -2. + static int malloc_info(FILE* stream); #endif // GLIBC }; diff --git a/src/hotspot/share/services/diagnosticCommand.cpp b/src/hotspot/share/services/diagnosticCommand.cpp index dd57581b859..750ecbc3555 100644 --- a/src/hotspot/share/services/diagnosticCommand.cpp +++ b/src/hotspot/share/services/diagnosticCommand.cpp @@ -63,6 +63,7 @@ #include "utilities/macros.hpp" #ifdef LINUX #include "trimCHeapDCmd.hpp" +#include "mallocInfoDcmd.hpp" #endif static void loadAgentModule(TRAPS) { @@ -126,6 +127,7 @@ void DCmdRegistrant::register_dcmds(){ #ifdef LINUX DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); #endif // LINUX DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); diff --git a/src/jdk.jcmd/share/man/jcmd.1 b/src/jdk.jcmd/share/man/jcmd.1 index 2b43431dbba..2f61ed240ce 100644 --- a/src/jdk.jcmd/share/man/jcmd.1 +++ b/src/jdk.jcmd/share/man/jcmd.1 @@ -775,6 +775,15 @@ Stops the remote management agent. Impact: Low --- no impact .RE .TP +\f[V]System.native_heap_info\f[R] (Linux only) +Prints information about native heap usage through malloc_info(3). +.RS +.PP +Impact: Low +.PP +Permission: \f[V]java.lang.management.ManagementPermission(monitor)\f[R] +.RE +.TP \f[V]System.trim_native_heap\f[R] (Linux only) Attempts to free up memory by trimming the C-heap. .RS diff --git a/test/hotspot/jtreg/serviceability/dcmd/vm/MallocInfoTest.java b/test/hotspot/jtreg/serviceability/dcmd/vm/MallocInfoTest.java new file mode 100644 index 00000000000..1d0049ed71a --- /dev/null +++ b/test/hotspot/jtreg/serviceability/dcmd/vm/MallocInfoTest.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2023, 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 jdk.test.lib.Platform; +import org.testng.annotations.Test; +import jdk.test.lib.dcmd.CommandExecutor; +import jdk.test.lib.dcmd.JMXExecutor; +import jdk.test.lib.process.OutputAnalyzer; + +/* + * @test + * @summary Test of diagnostic command System.native_heap_info + * @library /test/lib + * @requires (os.family=="linux") + * @modules java.base/jdk.internal.misc + * java.compiler + * java.management + * jdk.internal.jvmstat/sun.jvmstat.monitor + * @run testng MallocInfoTest + */ +public class MallocInfoTest { + public void run(CommandExecutor executor) { + OutputAnalyzer output = executor.execute("System.native_heap_info"); + if (!Platform.isMusl()) { + output.shouldNotContain("Error: "); + output.shouldContain("