1 Star 0 Fork 81

Benshuai5D/openjdk-1.8.0

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
8268893-jcmd-to-trim-the-glibc-heap.patch 28.26 KB
一键复制 编辑 原始数据 按行查看 历史
eapen 提交于 2023-01-11 10:00 . I69W1Y: Add feature and bug fix for 8u352
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678
From 1b97a08d822b7e2388ded07c696fffe70b39697a Mon Sep 17 00:00:00 2001
From: eapen <zhangyipeng7@huawei.com>
Date: Mon, 12 Dec 2022 17:40:09 +0800
Subject: [PATCH 12/33] I68TO2: 8268893: jcmd to trim the glibc heap
---
hotspot/src/os/linux/vm/os_linux.cpp | 57 ++++---
hotspot/src/os/linux/vm/os_linux.hpp | 17 ++
hotspot/src/os/linux/vm/trimCHeapDCmd.cpp | 77 +++++++++
hotspot/src/os/linux/vm/trimCHeapDCmd.hpp | 52 ++++++
.../src/share/vm/services/diagnosticCommand.cpp | 7 +
.../test/serviceability/dcmd/TrimLibcHeapTest.java | 53 ++++++
.../oracle/java/testlibrary/CommandExecutor.java | 73 ++++++++
.../java/testlibrary/CommandExecutorException.java | 36 ++++
.../com/oracle/java/testlibrary/JMXExecutor.java | 185 +++++++++++++++++++++
9 files changed, 532 insertions(+), 25 deletions(-)
create mode 100644 hotspot/src/os/linux/vm/trimCHeapDCmd.cpp
create mode 100644 hotspot/src/os/linux/vm/trimCHeapDCmd.hpp
create mode 100644 hotspot/test/serviceability/dcmd/TrimLibcHeapTest.java
create mode 100644 hotspot/test/testlibrary/com/oracle/java/testlibrary/CommandExecutor.java
create mode 100644 hotspot/test/testlibrary/com/oracle/java/testlibrary/CommandExecutorException.java
create mode 100644 hotspot/test/testlibrary/com/oracle/java/testlibrary/JMXExecutor.java
diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp
index 1a3504f..c687b1c 100644
--- a/hotspot/src/os/linux/vm/os_linux.cpp
+++ b/hotspot/src/os/linux/vm/os_linux.cpp
@@ -2290,44 +2290,51 @@ void os::Linux::print_system_memory_info(outputStream* st) {
st->cr();
}
-void os::Linux::print_process_memory_info(outputStream* st) {
-
- st->print_cr("Process Memory:");
-
- // Print virtual and resident set size; peak values; swap; and for
- // rss its components if the kernel is recent enough.
- ssize_t vmsize = -1, vmpeak = -1, vmswap = -1,
- vmrss = -1, vmhwm = -1, rssanon = -1, rssfile = -1, rssshmem = -1;
- const int num_values = 8;
- int num_found = 0;
+bool os::Linux::query_process_memory_info(os::Linux::meminfo_t* info) {
FILE* f = ::fopen("/proc/self/status", "r");
+ const int num_values = sizeof(os::Linux::meminfo_t) / sizeof(size_t);
+ int num_found = 0;
char buf[256];
+ info->vmsize = info->vmpeak = info->vmrss = info->vmhwm = info->vmswap =
+ info->rssanon = info->rssfile = info->rssshmem = -1;
if (f != NULL) {
while (::fgets(buf, sizeof(buf), f) != NULL && num_found < num_values) {
- if ( (vmsize == -1 && sscanf(buf, "VmSize: " SSIZE_FORMAT " kB", &vmsize) == 1) ||
- (vmpeak == -1 && sscanf(buf, "VmPeak: " SSIZE_FORMAT " kB", &vmpeak) == 1) ||
- (vmswap == -1 && sscanf(buf, "VmSwap: " SSIZE_FORMAT " kB", &vmswap) == 1) ||
- (vmhwm == -1 && sscanf(buf, "VmHWM: " SSIZE_FORMAT " kB", &vmhwm) == 1) ||
- (vmrss == -1 && sscanf(buf, "VmRSS: " SSIZE_FORMAT " kB", &vmrss) == 1) ||
- (rssanon == -1 && sscanf(buf, "RssAnon: " SSIZE_FORMAT " kB", &rssanon) == 1) ||
- (rssfile == -1 && sscanf(buf, "RssFile: " SSIZE_FORMAT " kB", &rssfile) == 1) ||
- (rssshmem == -1 && sscanf(buf, "RssShmem: " SSIZE_FORMAT " kB", &rssshmem) == 1)
+ if ( (info->vmsize == -1 && sscanf(buf, "VmSize: " SSIZE_FORMAT " kB", &info->vmsize) == 1) ||
+ (info->vmpeak == -1 && sscanf(buf, "VmPeak: " SSIZE_FORMAT " kB", &info->vmpeak) == 1) ||
+ (info->vmswap == -1 && sscanf(buf, "VmSwap: " SSIZE_FORMAT " kB", &info->vmswap) == 1) ||
+ (info->vmhwm == -1 && sscanf(buf, "VmHWM: " SSIZE_FORMAT " kB", &info->vmhwm) == 1) ||
+ (info->vmrss == -1 && sscanf(buf, "VmRSS: " SSIZE_FORMAT " kB", &info->vmrss) == 1) ||
+ (info->rssanon == -1 && sscanf(buf, "RssAnon: " SSIZE_FORMAT " kB", &info->rssanon) == 1) || // Needs Linux 4.5
+ (info->rssfile == -1 && sscanf(buf, "RssFile: " SSIZE_FORMAT " kB", &info->rssfile) == 1) || // Needs Linux 4.5
+ (info->rssshmem == -1 && sscanf(buf, "RssShmem: " SSIZE_FORMAT " kB", &info->rssshmem) == 1) // Needs Linux 4.5
)
{
num_found ++;
}
}
fclose(f);
+ return true;
+ }
+ return false;
+}
+
+void os::Linux::print_process_memory_info(outputStream* st) {
- st->print_cr("Virtual Size: " SSIZE_FORMAT "K (peak: " SSIZE_FORMAT "K)", vmsize, vmpeak);
- st->print("Resident Set Size: " SSIZE_FORMAT "K (peak: " SSIZE_FORMAT "K)", vmrss, vmhwm);
- if (rssanon != -1) { // requires kernel >= 4.5
+ st->print_cr("Process Memory:");
+
+ // Print virtual and resident set size; peak values; swap; and for
+ // rss its components if the kernel is recent enough.
+ meminfo_t info;
+ if (query_process_memory_info(&info)) {
+ st->print_cr("Virtual Size: " SSIZE_FORMAT "K (peak: " SSIZE_FORMAT "K)", info.vmsize, info.vmpeak);
+ st->print("Resident Set Size: " SSIZE_FORMAT "K (peak: " SSIZE_FORMAT "K)", info.vmrss, info.vmhwm);
+ if (info.rssanon != -1) { // requires kernel >= 4.5
st->print(" (anon: " SSIZE_FORMAT "K, file: " SSIZE_FORMAT "K, shmem: " SSIZE_FORMAT "K)",
- rssanon, rssfile, rssshmem);
+ info.rssanon, info.rssfile, info.rssshmem);
}
st->cr();
- if (vmswap != -1) { // requires kernel >= 2.6.34
- st->print_cr("Swapped out: " SSIZE_FORMAT "K", vmswap);
+ if (info.vmswap != -1) { // requires kernel >= 2.6.34
+ st->print_cr("Swapped out: " SSIZE_FORMAT "K", info.vmswap);
}
} else {
st->print_cr("Could not open /proc/self/status to get process memory related information");
@@ -2344,7 +2351,7 @@ void os::Linux::print_process_memory_info(outputStream* st) {
const size_t total_allocated = (size_t)(unsigned)mi.uordblks;
st->print("C-Heap outstanding allocations: " SIZE_FORMAT "K", total_allocated / K);
// Since mallinfo members are int, glibc values may have wrapped. Warn about this.
- if ((vmrss * K) > UINT_MAX && (vmrss * K) > (total_allocated + UINT_MAX)) {
+ if ((info.vmrss * K) > UINT_MAX && (info.vmrss * K) > (total_allocated + UINT_MAX)) {
st->print(" (may have wrapped)");
}
st->cr();
diff --git a/hotspot/src/os/linux/vm/os_linux.hpp b/hotspot/src/os/linux/vm/os_linux.hpp
index 066b03a..2c4efff 100644
--- a/hotspot/src/os/linux/vm/os_linux.hpp
+++ b/hotspot/src/os/linux/vm/os_linux.hpp
@@ -243,6 +243,23 @@ class Linux {
public:
static pthread_condattr_t* condAttr() { return _condattr; }
+ // Output structure for query_process_memory_info()
+ struct meminfo_t {
+ ssize_t vmsize; // current virtual size
+ ssize_t vmpeak; // peak virtual size
+ ssize_t vmrss; // current resident set size
+ ssize_t vmhwm; // peak resident set size
+ ssize_t vmswap; // swapped out
+ ssize_t rssanon; // resident set size (anonymous mappings, needs 4.5)
+ ssize_t rssfile; // resident set size (file mappings, needs 4.5)
+ ssize_t rssshmem; // resident set size (shared mappings, needs 4.5)
+ };
+
+ // Attempts to query memory information about the current process and return it in the output structure.
+ // May fail (returns false) or succeed (returns true) but not all output fields are available; unavailable
+ // fields will contain -1.
+ static bool query_process_memory_info(meminfo_t* info);
+
// Stack repair handling
// none present
diff --git a/hotspot/src/os/linux/vm/trimCHeapDCmd.cpp b/hotspot/src/os/linux/vm/trimCHeapDCmd.cpp
new file mode 100644
index 0000000..95d03d9
--- /dev/null
+++ b/hotspot/src/os/linux/vm/trimCHeapDCmd.cpp
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2021 SAP SE. All rights reserved.
+ * Copyright (c) 2021, 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 "runtime/os.hpp"
+#include "utilities/debug.hpp"
+#include "utilities/ostream.hpp"
+#include "trimCHeapDCmd.hpp"
+
+#include <malloc.h>
+
+void TrimCLibcHeapDCmd::execute(DCmdSource source, TRAPS) {
+#ifdef __GLIBC__
+ stringStream ss_report(1024); // Note: before calling trim
+
+ os::Linux::meminfo_t info1;
+ os::Linux::meminfo_t info2;
+ // Query memory before...
+ bool have_info1 = os::Linux::query_process_memory_info(&info1);
+
+ _output->print_cr("Attempting trim...");
+ ::malloc_trim(0);
+ _output->print_cr("Done.");
+
+ // ...and after trim.
+ bool have_info2 = os::Linux::query_process_memory_info(&info2);
+
+ // Print report both to output stream as well to UL
+ bool wrote_something = false;
+ if (have_info1 && have_info2) {
+ if (info1.vmsize != -1 && info2.vmsize != -1) {
+ ss_report.print_cr("Virtual size before: " SSIZE_FORMAT "k, after: " SSIZE_FORMAT "k, (" SSIZE_FORMAT "k)",
+ info1.vmsize, info2.vmsize, (info2.vmsize - info1.vmsize));
+ wrote_something = true;
+ }
+ if (info1.vmrss != -1 && info2.vmrss != -1) {
+ ss_report.print_cr("RSS before: " SSIZE_FORMAT "k, after: " SSIZE_FORMAT "k, (" SSIZE_FORMAT "k)",
+ info1.vmrss, info2.vmrss, (info2.vmrss - info1.vmrss));
+ wrote_something = true;
+ }
+ if (info1.vmswap != -1 && info2.vmswap != -1) {
+ ss_report.print_cr("Swap before: " SSIZE_FORMAT "k, after: " SSIZE_FORMAT "k, (" SSIZE_FORMAT "k)",
+ info1.vmswap, info2.vmswap, (info2.vmswap - info1.vmswap));
+ wrote_something = true;
+ }
+ }
+ if (!wrote_something) {
+ ss_report.print_raw("No details available.");
+ }
+
+ _output->print_raw(ss_report.base());
+#else
+ _output->print_cr("Not available.");
+#endif
+}
diff --git a/hotspot/src/os/linux/vm/trimCHeapDCmd.hpp b/hotspot/src/os/linux/vm/trimCHeapDCmd.hpp
new file mode 100644
index 0000000..4c5b5cc
--- /dev/null
+++ b/hotspot/src/os/linux/vm/trimCHeapDCmd.hpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2021 SAP SE. All rights reserved.
+ * Copyright (c) 2021, 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_TRIMCHEAPDCMD_HPP
+#define OS_LINUX_TRIMCHEAPDCMD_HPP
+
+#include "services/diagnosticCommand.hpp"
+
+class outputStream;
+
+class TrimCLibcHeapDCmd : public DCmd {
+public:
+ TrimCLibcHeapDCmd(outputStream* output, bool heap) : DCmd(output, heap) {}
+ static const char* name() {
+ return "System.trim_native_heap";
+ }
+ static const char* description() {
+ return "Attempts to free up memory by trimming the C-heap.";
+ }
+ static const char* impact() {
+ return "Low";
+ }
+ static const JavaPermission permission() {
+ JavaPermission p = { "java.lang.management.ManagementPermission", "control", NULL };
+ return p;
+ }
+ virtual void execute(DCmdSource source, TRAPS);
+};
+
+#endif // OS_LINUX_TRIMCHEAPDCMD_HPP
diff --git a/hotspot/src/share/vm/services/diagnosticCommand.cpp b/hotspot/src/share/vm/services/diagnosticCommand.cpp
index 358ec6e..60417b5 100644
--- a/hotspot/src/share/vm/services/diagnosticCommand.cpp
+++ b/hotspot/src/share/vm/services/diagnosticCommand.cpp
@@ -36,6 +36,10 @@
#include "utilities/macros.hpp"
#include "oops/objArrayOop.hpp"
+#ifdef LINUX
+#include "trimCHeapDCmd.hpp"
+#endif
+
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
void DCmdRegistrant::register_dcmds(){
@@ -65,6 +69,9 @@ void DCmdRegistrant::register_dcmds(){
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ThreadDumpDCmd>(full_export, true, false));
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<RotateGCLogDCmd>(full_export, true, false));
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ClassLoaderStatsDCmd>(full_export, true, false));
+#ifdef LINUX
+ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<TrimCLibcHeapDCmd>(full_export, true, false));
+#endif // LINUX
// Enhanced JMX Agent Support
// These commands won't be exported via the DiagnosticCommandMBean until an
diff --git a/hotspot/test/serviceability/dcmd/TrimLibcHeapTest.java b/hotspot/test/serviceability/dcmd/TrimLibcHeapTest.java
new file mode 100644
index 0000000..0fe8e35
--- /dev/null
+++ b/hotspot/test/serviceability/dcmd/TrimLibcHeapTest.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2021 SAP SE. All rights reserved.
+ * Copyright (c) 2021, 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 org.testng.annotations.Test;
+import com.oracle.java.testlibrary.*;
+
+/*
+ * @test
+ * @summary Test of diagnostic command VM.trim_libc_heap
+ * @library /testlibrary
+ * @requires os.family == "linux"
+ * @modules java.base/jdk.internal.misc
+ * java.compiler
+ * java.management
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
+ * @run testng TrimLibcHeapTest
+ */
+public class TrimLibcHeapTest {
+ public void run(CommandExecutor executor) {
+ OutputAnalyzer output = executor.execute("System.trim_native_heap");
+ output.reportDiagnosticSummary();
+ output.shouldMatch("(Done|Not available)"); // Not available could happen on Linux + non-glibc (eg. muslc)
+ if (output.firstMatch("Done") != null) {
+ output.shouldMatch("(Virtual size before|RSS before|Swap before|No details available)");
+ }
+ }
+
+ @Test
+ public void jmx() {
+ run(new JMXExecutor());
+ }
+}
diff --git a/hotspot/test/testlibrary/com/oracle/java/testlibrary/CommandExecutor.java b/hotspot/test/testlibrary/com/oracle/java/testlibrary/CommandExecutor.java
new file mode 100644
index 0000000..e95a437
--- /dev/null
+++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/CommandExecutor.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2015, 2016, 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.
+ */
+
+package com.oracle.java.testlibrary;
+
+/**
+ * Abstract base class for Diagnostic Command executors
+ */
+public abstract class CommandExecutor {
+
+ /**
+ * Execute a diagnostic command
+ *
+ * @param cmd The diagnostic command to execute
+ * @return an {@link jdk.testlibrary.OutputAnalyzer} encapsulating the output of the command
+ * @throws CommandExecutorException if there is an exception on the "calling side" while trying to execute the
+ * Diagnostic Command. Exceptions thrown on the remote side are available as textual representations in
+ * stderr, regardless of the specific executor used.
+ */
+ public final OutputAnalyzer execute(String cmd) throws CommandExecutorException {
+ return execute(cmd, false);
+ }
+
+ /**
+ * Execute a diagnostic command
+ *
+ * @param cmd The diagnostic command to execute
+ * @param silent Do not print the command output
+ * @return an {@link jdk.testlibrary.OutputAnalyzer} encapsulating the output of the command
+ * @throws CommandExecutorException if there is an exception on the "calling side" while trying to execute the
+ * Diagnostic Command. Exceptions thrown on the remote side are available as textual representations in
+ * stderr, regardless of the specific executor used.
+ */
+ public final OutputAnalyzer execute(String cmd, boolean silent) throws CommandExecutorException {
+ if (!silent) {
+ System.out.printf("Running DCMD '%s' through '%s'%n", cmd, this.getClass().getSimpleName());
+ }
+
+ OutputAnalyzer oa = executeImpl(cmd);
+
+ if (!silent) {
+ System.out.println("---------------- stdout ----------------");
+ System.out.println(oa.getStdout());
+ System.out.println("---------------- stderr ----------------");
+ System.out.println(oa.getStderr());
+ System.out.println("----------------------------------------");
+ System.out.println();
+ }
+ return oa;
+ }
+
+ protected abstract OutputAnalyzer executeImpl(String cmd) throws CommandExecutorException;
+}
diff --git a/hotspot/test/testlibrary/com/oracle/java/testlibrary/CommandExecutorException.java b/hotspot/test/testlibrary/com/oracle/java/testlibrary/CommandExecutorException.java
new file mode 100644
index 0000000..1857a23
--- /dev/null
+++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/CommandExecutorException.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2015, 2016, 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.
+ */
+
+package com.oracle.java.testlibrary;
+
+/**
+ * CommandExecutorException encapsulates exceptions thrown (on the "calling side") from the execution of Diagnostic
+ * Commands
+ */
+public class CommandExecutorException extends RuntimeException {
+ private static final long serialVersionUID = -7039597746579144280L;
+
+ public CommandExecutorException(String message, Throwable e) {
+ super(message, e);
+ }
+}
diff --git a/hotspot/test/testlibrary/com/oracle/java/testlibrary/JMXExecutor.java b/hotspot/test/testlibrary/com/oracle/java/testlibrary/JMXExecutor.java
new file mode 100644
index 0000000..317fc5c
--- /dev/null
+++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/JMXExecutor.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2015, 2016, 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.
+ */
+
+package com.oracle.java.testlibrary;
+
+import javax.management.*;
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXConnectorFactory;
+import javax.management.remote.JMXServiceURL;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+import java.lang.management.ManagementFactory;
+
+import java.util.HashMap;
+
+/**
+ * Executes Diagnostic Commands on the target VM (specified by a host/port combination or a full JMX Service URL) using
+ * the JMX interface. If the target is not the current VM, the JMX Remote interface must be enabled beforehand.
+ */
+public class JMXExecutor extends CommandExecutor {
+
+ private final MBeanServerConnection mbs;
+
+ /**
+ * Instantiates a new JMXExecutor targeting the current VM
+ */
+ public JMXExecutor() {
+ super();
+ mbs = ManagementFactory.getPlatformMBeanServer();
+ }
+
+ /**
+ * Instantiates a new JMXExecutor targeting the VM indicated by the given host/port combination or a full JMX
+ * Service URL
+ *
+ * @param target a host/port combination on the format "host:port" or a full JMX Service URL of the target VM
+ */
+ public JMXExecutor(String target) {
+ String urlStr;
+
+ if (target.matches("^\\w[\\w\\-]*(\\.[\\w\\-]+)*:\\d+$")) {
+ /* Matches "hostname:port" */
+ urlStr = String.format("service:jmx:rmi:///jndi/rmi://%s/jmxrmi", target);
+ } else if (target.startsWith("service:")) {
+ urlStr = target;
+ } else {
+ throw new IllegalArgumentException("Could not recognize target string: " + target);
+ }
+
+ try {
+ JMXServiceURL url = new JMXServiceURL(urlStr);
+ JMXConnector c = JMXConnectorFactory.connect(url, new HashMap<>());
+ mbs = c.getMBeanServerConnection();
+ } catch (IOException e) {
+ throw new CommandExecutorException("Could not initiate connection to target: " + target, e);
+ }
+ }
+
+ protected OutputAnalyzer executeImpl(String cmd) throws CommandExecutorException {
+ String stdout = "";
+ String stderr = "";
+
+ String[] cmdParts = cmd.split(" ", 2);
+ String operation = commandToMethodName(cmdParts[0]);
+ Object[] dcmdArgs = produceArguments(cmdParts);
+ String[] signature = {String[].class.getName()};
+
+ ObjectName beanName = getMBeanName();
+
+ try {
+ stdout = (String) mbs.invoke(beanName, operation, dcmdArgs, signature);
+ }
+
+ /* Failures on the "local" side, the one invoking the command. */
+ catch (ReflectionException e) {
+ Throwable cause = e.getCause();
+ if (cause instanceof NoSuchMethodException) {
+ /* We want JMXExecutor to match the behavior of the other CommandExecutors */
+ String message = "Unknown diagnostic command: " + operation;
+ stderr = exceptionTraceAsString(new IllegalArgumentException(message, e));
+ } else {
+ rethrowExecutorException(operation, dcmdArgs, e);
+ }
+ }
+
+ /* Failures on the "local" side, the one invoking the command. */
+ catch (InstanceNotFoundException | IOException e) {
+ rethrowExecutorException(operation, dcmdArgs, e);
+ }
+
+ /* Failures on the remote side, the one executing the invoked command. */
+ catch (MBeanException e) {
+ stdout = exceptionTraceAsString(e);
+ }
+
+ return new OutputAnalyzer(stdout, stderr);
+ }
+
+ private void rethrowExecutorException(String operation, Object[] dcmdArgs,
+ Exception e) throws CommandExecutorException {
+ String message = String.format("Could not invoke: %s %s", operation,
+ String.join(" ", (String[]) dcmdArgs[0]));
+ throw new CommandExecutorException(message, e);
+ }
+
+ private ObjectName getMBeanName() throws CommandExecutorException {
+ String MBeanName = "com.sun.management:type=DiagnosticCommand";
+
+ try {
+ return new ObjectName(MBeanName);
+ } catch (MalformedObjectNameException e) {
+ String message = "MBean not found: " + MBeanName;
+ throw new CommandExecutorException(message, e);
+ }
+ }
+
+ private Object[] produceArguments(String[] cmdParts) {
+ Object[] dcmdArgs = {new String[0]}; /* Default: No arguments */
+
+ if (cmdParts.length == 2) {
+ dcmdArgs[0] = cmdParts[1].split(" ");
+ }
+ return dcmdArgs;
+ }
+
+ /**
+ * Convert from diagnostic command to MBean method name
+ *
+ * Examples:
+ * help --> help
+ * VM.version --> vmVersion
+ * VM.command_line --> vmCommandLine
+ */
+ private static String commandToMethodName(String cmd) {
+ String operation = "";
+ boolean up = false; /* First letter is to be lower case */
+
+ /*
+ * If a '.' or '_' is encountered it is not copied,
+ * instead the next character will be converted to upper case
+ */
+ for (char c : cmd.toCharArray()) {
+ if (('.' == c) || ('_' == c)) {
+ up = true;
+ } else if (up) {
+ operation = operation.concat(Character.toString(c).toUpperCase());
+ up = false;
+ } else {
+ operation = operation.concat(Character.toString(c).toLowerCase());
+ }
+ }
+
+ return operation;
+ }
+
+ private static String exceptionTraceAsString(Throwable cause) {
+ StringWriter sw = new StringWriter();
+ cause.printStackTrace(new PrintWriter(sw));
+ return sw.toString();
+ }
+
+}
--
1.8.3.1
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/zhangyunbo7/openjdk-1.8.0.git
git@gitee.com:zhangyunbo7/openjdk-1.8.0.git
zhangyunbo7
openjdk-1.8.0
openjdk-1.8.0
master

搜索帮助