代码拉取完成,页面将自动刷新
同步操作将从 src-openEuler/openjdk-1.8.0 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
Date: Wed, 31 May 2023 03:55:21 +0000
Subject: [PATCH 04/59] 8193710: jcmd -l and jps commands do not list Java processes running in Docker containers
Bug url: https://bugs.openjdk.org/browse/JDK-8193710
---
hotspot/src/os/linux/vm/perfMemory_linux.cpp | 102 ++++++--
.../classes/sun/jvmstat/PlatformSupport.java | 114 +++++++++
.../sun/jvmstat/PlatformSupportImpl.java | 227 ++++++++++++++++++
.../protocol/local/LocalVmManager.java | 93 +++----
.../monitor/protocol/local/PerfDataFile.java | 179 ++++++++------
5 files changed, 582 insertions(+), 133 deletions(-)
create mode 100644 jdk/src/share/classes/sun/jvmstat/PlatformSupport.java
create mode 100644 jdk/src/share/classes/sun/jvmstat/PlatformSupportImpl.java
diff --git a/hotspot/src/os/linux/vm/perfMemory_linux.cpp b/hotspot/src/os/linux/vm/perfMemory_linux.cpp
index 8293b7168..b45032edb 100644
--- a/hotspot/src/os/linux/vm/perfMemory_linux.cpp
+++ b/hotspot/src/os/linux/vm/perfMemory_linux.cpp
@@ -147,11 +147,23 @@ static void save_memory_to_file(char* addr, size_t size) {
// return the user specific temporary directory name.
//
+// If containerized process, get dirname of
+// /proc/{vmid}/root/tmp/{PERFDATA_NAME_user}
+// otherwise /tmp/{PERFDATA_NAME_user}
+//
// the caller is expected to free the allocated memory.
//
-static char* get_user_tmp_dir(const char* user) {
+#define TMP_BUFFER_LEN (4+22)
+static char* get_user_tmp_dir(const char* user, int vmid, int nspid) {
+ char buffer[TMP_BUFFER_LEN];
+ char* tmpdir = (char *)os::get_temp_directory();
+ assert(strlen(tmpdir) == 4, "No longer using /tmp - update buffer size");
+
+ if (nspid != -1) {
+ jio_snprintf(buffer, TMP_BUFFER_LEN, "/proc/%d/root%s", vmid, tmpdir);
+ tmpdir = buffer;
+ }
- const char* tmpdir = os::get_temp_directory();
const char* perfdir = PERFDATA_NAME;
size_t nbytes = strlen(tmpdir) + strlen(perfdir) + strlen(user) + 3;
char* dirname = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal);
@@ -500,7 +512,10 @@ static char* get_user_name(uid_t uid) {
//
// the caller is expected to free the allocated memory.
//
-static char* get_user_name_slow(int vmid, TRAPS) {
+// If nspid != -1, look in /proc/{vmid}/root/tmp for directories
+// containing nspid, otherwise just look for vmid in /tmp
+//
+static char* get_user_name_slow(int vmid, int nspid, TRAPS) {
// short circuit the directory search if the process doesn't even exist.
if (kill(vmid, 0) == OS_ERR) {
@@ -516,8 +531,19 @@ static char* get_user_name_slow(int vmid, TRAPS) {
// directory search
char* oldest_user = NULL;
time_t oldest_ctime = 0;
+ char buffer[TMP_BUFFER_LEN];
+ int searchpid;
+ char* tmpdirname = (char *)os::get_temp_directory();
+ assert(strlen(tmpdirname) == 4, "No longer using /tmp - update buffer size");
- const char* tmpdirname = os::get_temp_directory();
+ if (nspid == -1) {
+ searchpid = vmid;
+ }
+ else {
+ jio_snprintf(buffer, MAXPATHLEN, "/proc/%d/root%s", vmid, tmpdirname);
+ tmpdirname = buffer;
+ searchpid = nspid;
+ }
// open the temp directory
DIR* tmpdirp = os::opendir(tmpdirname);
@@ -528,7 +554,7 @@ static char* get_user_name_slow(int vmid, TRAPS) {
}
// for each entry in the directory that matches the pattern hsperfdata_*,
- // open the directory and check if the file for the given vmid exists.
+ // open the directory and check if the file for the given vmid or nspid exists.
// The file with the expected name and the latest creation date is used
// to determine the user name for the process id.
//
@@ -571,7 +597,7 @@ static char* get_user_name_slow(int vmid, TRAPS) {
errno = 0;
while ((udentry = os::readdir(subdirp)) != NULL) {
- if (filename_to_pid(udentry->d_name) == vmid) {
+ if (filename_to_pid(udentry->d_name) == searchpid) {
struct stat statbuf;
int result;
@@ -620,10 +646,51 @@ static char* get_user_name_slow(int vmid, TRAPS) {
return(oldest_user);
}
+// Determine if the vmid is the parent pid
+// for a child in a PID namespace.
+// return the namespace pid if so, otherwise -1
+static int get_namespace_pid(int vmid) {
+ char fname[24];
+ int retpid = -1;
+
+ snprintf(fname, sizeof(fname), "/proc/%d/status", vmid);
+ FILE *fp = fopen(fname, "r");
+
+ if (fp) {
+ int pid, nspid;
+ int ret;
+ while (!feof(fp)) {
+ ret = fscanf(fp, "NSpid: %d %d", &pid, &nspid);
+ if (ret == 1) {
+ break;
+ }
+ if (ret == 2) {
+ retpid = nspid;
+ break;
+ }
+ for (;;) {
+ int ch = fgetc(fp);
+ if (ch == EOF || ch == (int)'\n') break;
+ }
+ }
+ fclose(fp);
+ }
+ return retpid;
+}
+
// return the name of the user that owns the JVM indicated by the given vmid.
//
-static char* get_user_name(int vmid, TRAPS) {
- return get_user_name_slow(vmid, THREAD);
+static char* get_user_name(int vmid, int *nspid, TRAPS) {
+ char *result = get_user_name_slow(vmid, *nspid, THREAD);
+
+ // If we are examining a container process without PID namespaces enabled
+ // we need to use /proc/{pid}/root/tmp to find hsperfdata files.
+ if (result == NULL) {
+ result = get_user_name_slow(vmid, vmid, THREAD);
+ // Enable nspid logic going forward
+ if (result != NULL) *nspid = vmid;
+ }
+ return result;
}
// return the file name of the backing store file for the named
@@ -631,13 +698,15 @@ static char* get_user_name(int vmid, TRAPS) {
//
// the caller is expected to free the allocated memory.
//
-static char* get_sharedmem_filename(const char* dirname, int vmid) {
+static char* get_sharedmem_filename(const char* dirname, int vmid, int nspid) {
+
+ int pid = (nspid == -1) ? vmid : nspid;
// add 2 for the file separator and a null terminator.
size_t nbytes = strlen(dirname) + UINT_CHARS + 2;
char* name = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal);
- snprintf(name, nbytes, "%s/%d", dirname, vmid);
+ snprintf(name, nbytes, "%s/%d", dirname, pid);
return name;
}
@@ -929,8 +998,8 @@ static char* mmap_create_shared(size_t size) {
if (user_name == NULL)
return NULL;
- char* dirname = get_user_tmp_dir(user_name);
- char* filename = get_sharedmem_filename(dirname, vmid);
+ char* dirname = get_user_tmp_dir(user_name, vmid, -1);
+ char* filename = get_sharedmem_filename(dirname, vmid, -1);
// get the short filename
char* short_filename = strrchr(filename, '/');
if (short_filename == NULL) {
@@ -1076,8 +1145,11 @@ static void mmap_attach_shared(const char* user, int vmid, PerfMemory::PerfMemor
"Illegal access mode");
}
+ // determine if vmid is for a containerized process
+ int nspid = get_namespace_pid(vmid);
+
if (user == NULL || strlen(user) == 0) {
- luser = get_user_name(vmid, CHECK);
+ luser = get_user_name(vmid, &nspid, CHECK);
}
else {
luser = user;
@@ -1088,7 +1160,7 @@ static void mmap_attach_shared(const char* user, int vmid, PerfMemory::PerfMemor
"Could not map vmid to user Name");
}
- char* dirname = get_user_tmp_dir(luser);
+ char* dirname = get_user_tmp_dir(luser, vmid, nspid);
// since we don't follow symbolic links when creating the backing
// store file, we don't follow them when attaching either.
@@ -1099,7 +1171,7 @@ static void mmap_attach_shared(const char* user, int vmid, PerfMemory::PerfMemor
"Process not found");
}
- char* filename = get_sharedmem_filename(dirname, vmid);
+ char* filename = get_sharedmem_filename(dirname, vmid, nspid);
// copy heap memory to resource memory. the open_sharedmem_file
// method below need to use the filename, but could throw an
diff --git a/jdk/src/share/classes/sun/jvmstat/PlatformSupport.java b/jdk/src/share/classes/sun/jvmstat/PlatformSupport.java
new file mode 100644
index 000000000..84f3b2274
--- /dev/null
+++ b/jdk/src/share/classes/sun/jvmstat/PlatformSupport.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2018, 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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 sun.jvmstat;
+
+import java.io.File;
+import java.lang.reflect.Constructor;
+import java.util.Collections;
+import java.util.List;
+import sun.misc.VMSupport;
+
+/*
+ * Support routines handling temp directory locating
+ * and process ID extraction.
+ */
+public class PlatformSupport {
+ private static final String tmpDirName;
+ static {
+ /*
+ * For this to work, the target VM and this code need to use
+ * the same directory. Instead of guessing which directory the
+ * VM is using, we will ask.
+ */
+ String tmpdir = VMSupport.getVMTemporaryDirectory();
+
+ /*
+ * Assure that the string returned has a trailing File.separator
+ * character. This check was added because the Linux implementation
+ * changed such that the java.io.tmpdir string no longer terminates
+ * with a File.separator character.
+ */
+ if (tmpdir.lastIndexOf(File.separator) != (tmpdir.length()-1)) {
+ tmpdir = tmpdir + File.separator;
+ }
+ tmpDirName = tmpdir;
+ }
+
+ public static PlatformSupport getInstance() {
+ try {
+ Class<?> c = Class.forName("sun.jvmstat.PlatformSupportImpl");
+ @SuppressWarnings("unchecked")
+ Constructor<PlatformSupport> cntr = (Constructor<PlatformSupport>) c.getConstructor();
+ return cntr.newInstance();
+ } catch (ClassNotFoundException e) {
+ return new PlatformSupport();
+ } catch (ReflectiveOperationException e) {
+ throw new InternalError(e);
+ }
+ }
+
+ // package-private
+ PlatformSupport() {}
+
+ /*
+ * Return the OS specific temporary directory
+ */
+ public static String getTemporaryDirectory() {
+ return tmpDirName;
+ }
+
+ /*
+ * Return a list of the temporary directories that the VM uses
+ * for the attach and perf data files. This function returns
+ * the traditional temp directory in addition to any paths
+ * accessible by the host which map to temp directories used
+ * by containers. The container functionality is only currently
+ * supported on Linux platforms.
+ *
+ * It is important that this directory is well-known and the
+ * same for all VM instances. It cannot be affected by configuration
+ * variables such as java.io.tmpdir.
+ */
+ public List<String> getTemporaryDirectories(int vmid) {
+ // Add the default temporary directory only
+ return Collections.singletonList(tmpDirName);
+ }
+
+ /*
+ * Extract the host PID from a file path.
+ */
+ public int getLocalVmId(File file) throws NumberFormatException {
+ return Integer.parseInt(file.getName());
+ }
+
+
+ /*
+ * Return the inner most namespaced PID if there is one,
+ * otherwise return the original PID.
+ */
+ public int getNamespaceVmId(int pid) {
+ return pid;
+ }
+}
diff --git a/jdk/src/share/classes/sun/jvmstat/PlatformSupportImpl.java b/jdk/src/share/classes/sun/jvmstat/PlatformSupportImpl.java
new file mode 100644
index 000000000..4d1d718ab
--- /dev/null
+++ b/jdk/src/share/classes/sun/jvmstat/PlatformSupportImpl.java
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2018, 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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 sun.jvmstat;
+
+import java.io.*;
+import java.util.*;
+import java.util.regex.*;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.Files;
+import java.nio.charset.*;
+
+/*
+ * Linux specific implementation of the PlatformSupport routines
+ * providing process ID and temp directory support for host and
+ * cgroup container processes.
+ */
+public class PlatformSupportImpl extends PlatformSupport {
+ private static final String containerTmpPath = "/root" + getTemporaryDirectory();
+ private static final String pidPatternStr = "^[0-9]+$";
+
+ /*
+ * Return the temporary directories that the VM uses for the attach
+ * and perf data files. This function returns the traditional
+ * /tmp directory in addition to paths within the /proc file system
+ * allowing access to container tmp directories such as /proc/{pid}/root/tmp.
+ *
+ * It is important that this directory is well-known and the
+ * same for all VM instances. It cannot be affected by configuration
+ * variables such as java.io.tmpdir.
+ *
+ * Implementation Details:
+ *
+ * Java processes that run in docker containers are typically running
+ * under cgroups with separate pid namespaces which means that pids
+ * within the container are different that the pid which is visible
+ * from the host. The container pids typically start with 1 and
+ * increase. The java process running in the container will use these
+ * pids when creating the hsperfdata files. In order to locate java
+ * processes that are running in containers, we take advantage of
+ * the Linux proc file system which maps the containers tmp directory
+ * to the hosts under /proc/{hostpid}/root/tmp. We use the /proc status
+ * file /proc/{hostpid}/status to determine the containers pid and
+ * then access the hsperfdata file. The status file contains an
+ * entry "NSPid:" which shows the mapping from the hostpid to the
+ * containers pid.
+ *
+ * Example:
+ *
+ * NSPid: 24345 11
+ *
+ * In this example process 24345 is visible from the host,
+ * is running under the PID namespace and has a container specific
+ * pid of 11.
+ *
+ * The search for Java processes is done by first looking in the
+ * traditional /tmp for host process hsperfdata files and then
+ * the search will container in every /proc/{pid}/root/tmp directory.
+ * There are of course added complications to this search that
+ * need to be taken into account.
+ *
+ * 1. duplication of tmp directories
+ *
+ * /proc/{hostpid}/root/tmp directories exist for many processes
+ * that are running on a Linux kernel that has cgroups enabled even
+ * if they are not running in a container. To avoid this duplication,
+ * we compare the inode of the /proc tmp directories to /tmp and
+ * skip these duplicated directories.
+ *
+ * 2. Containerized processes without PID namespaces being enabled.
+ *
+ * If a container is running a Java process without namespaces being
+ * enabled, an hsperfdata file will only be located at
+ * /proc/{hostpid}/root/tmp/{hostpid}. This is handled by
+ * checking the last component in the path for both the hostpid
+ * and potential namespacepids (if one exists).
+ */
+ public List<String> getTemporaryDirectories(int pid) {
+ FilenameFilter pidFilter;
+ Matcher pidMatcher;
+ Pattern pidPattern = Pattern.compile(pidPatternStr);
+ long tmpInode = 0;
+
+ File procdir = new File("/proc");
+
+ if (pid != 0) {
+ pidPattern = Pattern.compile(Integer.toString(pid));
+ }
+ else {
+ pidPattern = Pattern.compile(pidPatternStr);
+ }
+ pidMatcher = pidPattern.matcher("");
+
+ // Add the default temporary directory first
+ List<String> v = new ArrayList<>();
+ v.add(getTemporaryDirectory());
+
+ try {
+ File f = new File(getTemporaryDirectory());
+ tmpInode = (Long)Files.getAttribute(f.toPath(), "unix:ino");
+ }
+ catch (IOException e) {}
+
+ pidFilter = new FilenameFilter() {
+ public boolean accept(File dir, String name) {
+ if (!dir.isDirectory())
+ return false;
+ pidMatcher.reset(name);
+ return pidMatcher.matches();
+ }
+ };
+
+ File[] dirs = procdir.listFiles(pidFilter);
+
+ // Add all unique /proc/{pid}/root/tmp dirs that are not mapped to /tmp
+ for (File dir : dirs) {
+ String containerTmpDir = dir.getAbsolutePath() + containerTmpPath;
+ File containerFile = new File(containerTmpDir);
+
+ try {
+ long procInode = (Long)Files.getAttribute(containerFile.toPath(), "unix:ino");
+ if (containerFile.exists() && containerFile.isDirectory() &&
+ containerFile.canRead() && procInode != tmpInode) {
+ v.add(containerTmpDir);
+ }
+ }
+ catch (IOException e) {}
+ }
+
+ return v;
+ }
+
+
+ /*
+ * Extract either the host PID or the NameSpace PID
+ * from a file path.
+ *
+ * File path should be in 1 of these 2 forms:
+ *
+ * /proc/{pid}/root/tmp/hsperfdata_{user}/{nspid}
+ * or
+ * /tmp/hsperfdata_{user}/{pid}
+ *
+ * In either case we want to return {pid} and NOT {nspid}
+ *
+ * This function filters out host pids which do not have
+ * associated hsperfdata files. This is due to the fact that
+ * getTemporaryDirectories will return /proc/{pid}/root/tmp
+ * paths for all container processes whether they are java
+ * processes or not causing duplicate matches.
+ */
+ public int getLocalVmId(File file) throws NumberFormatException {
+ String p = file.getAbsolutePath();
+ String s[] = p.split("\\/");
+
+ // Determine if this file is from a container
+ if (s.length == 7 && s[1].equals("proc")) {
+ int hostpid = Integer.parseInt(s[2]);
+ int nspid = Integer.parseInt(s[6]);
+ if (nspid == hostpid || nspid == getNamespaceVmId(hostpid)) {
+ return hostpid;
+ }
+ else {
+ return -1;
+ }
+ }
+ else {
+ return Integer.parseInt(file.getName());
+ }
+ }
+
+
+ /*
+ * Return the inner most namespaced PID if there is one,
+ * otherwise return the original PID.
+ */
+ public int getNamespaceVmId(int pid) {
+ // Assuming a real procfs sits beneath, reading this doesn't block
+ // nor will it consume a lot of memory.
+ Path statusPath = Paths.get("/proc", Integer.toString(pid), "status");
+ if (Files.notExists(statusPath)) {
+ return pid; // Likely a bad pid, but this is properly handled later.
+ }
+
+ try {
+ for (String line : Files.readAllLines(statusPath, StandardCharsets.UTF_8)) {
+ String[] parts = line.split(":");
+ if (parts.length == 2 && parts[0].trim().equals("NSpid")) {
+ parts = parts[1].trim().split("\\s+");
+ // The last entry represents the PID the JVM "thinks" it is.
+ // Even in non-namespaced pids these entries should be
+ // valid. You could refer to it as the inner most pid.
+ int ns_pid = Integer.parseInt(parts[parts.length - 1]);
+ return ns_pid;
+ }
+ }
+ // Old kernels may not have NSpid field (i.e. 3.10).
+ // Fallback to original pid in the event we cannot deduce.
+ return pid;
+ } catch (NumberFormatException | IOException x) {
+ return pid;
+ }
+ }
+}
diff --git a/jdk/src/share/classes/sun/jvmstat/perfdata/monitor/protocol/local/LocalVmManager.java b/jdk/src/share/classes/sun/jvmstat/perfdata/monitor/protocol/local/LocalVmManager.java
index fde75fb2d..35d25700d 100644
--- a/jdk/src/share/classes/sun/jvmstat/perfdata/monitor/protocol/local/LocalVmManager.java
+++ b/jdk/src/share/classes/sun/jvmstat/perfdata/monitor/protocol/local/LocalVmManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2018, 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
@@ -45,7 +45,7 @@ import java.io.*;
*/
public class LocalVmManager {
private String userName; // user name for monitored jvm
- private File tmpdir;
+ private List<String> tmpdirs;
private Pattern userPattern;
private Matcher userMatcher;
private FilenameFilter userFilter;
@@ -77,8 +77,9 @@ public class LocalVmManager {
public LocalVmManager(String user) {
this.userName = user;
+
if (userName == null) {
- tmpdir = new File(PerfDataFile.getTempDirectory());
+ tmpdirs = PerfDataFile.getTempDirectories(null, 0);
userPattern = Pattern.compile(PerfDataFile.userDirNamePattern);
userMatcher = userPattern.matcher("");
@@ -89,7 +90,7 @@ public class LocalVmManager {
}
};
} else {
- tmpdir = new File(PerfDataFile.getTempDirectory(userName));
+ tmpdirs = PerfDataFile.getTempDirectories(userName, 0);
}
filePattern = Pattern.compile(PerfDataFile.fileNamePattern);
@@ -134,65 +135,73 @@ public class LocalVmManager {
*/
Set<Integer> jvmSet = new HashSet<Integer>();
- if (! tmpdir.isDirectory()) {
- return jvmSet;
- }
+ for (String dir : tmpdirs) {
+ File tmpdir = new File(dir);
+ if (! tmpdir.isDirectory()) {
+ continue;
+ }
- if (userName == null) {
- /*
- * get a list of all of the user temporary directories and
- * iterate over the list to find any files within those directories.
- */
- File[] dirs = tmpdir.listFiles(userFilter);
-
- for (int i = 0 ; i < dirs.length; i ++) {
- if (!dirs[i].isDirectory()) {
- continue;
+ if (userName == null) {
+ /*
+ * get a list of all of the user temporary directories and
+ * iterate over the list to find any files within those directories.
+ */
+ File[] dirs = tmpdir.listFiles(userFilter);
+ for (int i = 0 ; i < dirs.length; i ++) {
+ if (!dirs[i].isDirectory()) {
+ continue;
+ }
+
+ // get a list of files from the directory
+ File[] files = dirs[i].listFiles(fileFilter);
+ if (files != null) {
+ for (int j = 0; j < files.length; j++) {
+ if (files[j].isFile() && files[j].canRead()) {
+ int vmid = PerfDataFile.getLocalVmId(files[j]);
+ if (vmid != -1) {
+ jvmSet.add(vmid);
+ }
+ }
+ }
+ }
}
+ } else {
+ /*
+ * Check if the user directory can be accessed. Any of these
+ * conditions may have asynchronously changed between subsequent
+ * calls to this method.
+ */
- // get a list of files from the directory
- File[] files = dirs[i].listFiles(fileFilter);
+ // get the list of files from the specified user directory
+ File[] files = tmpdir.listFiles(fileFilter);
if (files != null) {
for (int j = 0; j < files.length; j++) {
if (files[j].isFile() && files[j].canRead()) {
- jvmSet.add(new Integer(
- PerfDataFile.getLocalVmId(files[j])));
+ int vmid = PerfDataFile.getLocalVmId(files[j]);
+ if (vmid != -1) {
+ jvmSet.add(vmid);
+ }
}
}
}
}
- } else {
- /*
- * Check if the user directory can be accessed. Any of these
- * conditions may have asynchronously changed between subsequent
- * calls to this method.
- */
- // get the list of files from the specified user directory
- File[] files = tmpdir.listFiles(fileFilter);
+ // look for any 1.4.1 files
+ File[] files = tmpdir.listFiles(tmpFileFilter);
if (files != null) {
for (int j = 0; j < files.length; j++) {
if (files[j].isFile() && files[j].canRead()) {
- jvmSet.add(new Integer(
- PerfDataFile.getLocalVmId(files[j])));
+ int vmid = PerfDataFile.getLocalVmId(files[j]);
+ if (vmid != -1) {
+ jvmSet.add(vmid);
+ }
}
}
}
}
- // look for any 1.4.1 files
- File[] files = tmpdir.listFiles(tmpFileFilter);
- if (files != null) {
- for (int j = 0; j < files.length; j++) {
- if (files[j].isFile() && files[j].canRead()) {
- jvmSet.add(new Integer(
- PerfDataFile.getLocalVmId(files[j])));
- }
- }
- }
-
return jvmSet;
}
}
diff --git a/jdk/src/share/classes/sun/jvmstat/perfdata/monitor/protocol/local/PerfDataFile.java b/jdk/src/share/classes/sun/jvmstat/perfdata/monitor/protocol/local/PerfDataFile.java
index 62c64795b..26045ac5e 100644
--- a/jdk/src/share/classes/sun/jvmstat/perfdata/monitor/protocol/local/PerfDataFile.java
+++ b/jdk/src/share/classes/sun/jvmstat/perfdata/monitor/protocol/local/PerfDataFile.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2018 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
@@ -26,7 +26,11 @@
package sun.jvmstat.perfdata.monitor.protocol.local;
import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
import java.io.FilenameFilter;
+import sun.jvmstat.PlatformSupport;
/**
* Class to provide translations from the local Vm Identifier
@@ -44,11 +48,6 @@ import java.io.FilenameFilter;
public class PerfDataFile {
private PerfDataFile() { };
- /**
- * The name of the of the system dependent temporary directory
- */
- public static final String tmpDirName;
-
/**
* The file name prefix for PerfData shared memory files.
* <p>
@@ -79,6 +78,12 @@ public class PerfDataFile {
"^hsperfdata_[0-9]+(_[1-2]+)?$";
+ /**
+ * Platform Specific methods for looking up temporary directories
+ * and process IDs.
+ */
+ private static final PlatformSupport platSupport = PlatformSupport.getInstance();
+
/**
* Get a File object for the instrumentation backing store file
* for the JVM identified by the given local Vm Identifier.
@@ -93,7 +98,7 @@ public class PerfDataFile {
* @return File - a File object to the backing store file for the named
* shared memory region of the target JVM.
* @see java.io.File
- * @see #getTempDirectory()
+ * @see #getTempDirectories()
*/
public static File getFile(int lvmid) {
if (lvmid == 0) {
@@ -106,56 +111,65 @@ public class PerfDataFile {
return null;
}
- /*
- * iterate over all files in all directories in tmpDirName that
- * match the file name patterns.
- */
- File tmpDir = new File(tmpDirName);
- String[] files = tmpDir.list(new FilenameFilter() {
- public boolean accept(File dir, String name) {
- if (!name.startsWith(dirNamePrefix)) {
- return false;
- }
- File candidate = new File(dir, name);
- return ((candidate.isDirectory() || candidate.isFile())
- && candidate.canRead());
- }
- });
-
- long newestTime = 0;
+ List<String> tmpDirs = getTempDirectories(null, lvmid);
File newest = null;
- for (int i = 0; i < files.length; i++) {
- File f = new File(tmpDirName + files[i]);
- File candidate = null;
+ for (String dir : tmpDirs) {
+ /*
+ * iterate over all files in all directories in this tmpDir that
+ * match the file name patterns.
+ */
+ File tmpDir = new File(dir);
+ String[] files = tmpDir.list(new FilenameFilter() {
+ public boolean accept(File dir, String name) {
+ if (!name.startsWith(dirNamePrefix)) {
+ return false;
+ }
+ File candidate = new File(dir, name);
+ return ((candidate.isDirectory() || candidate.isFile())
+ && candidate.canRead());
+ }
+ });
- if (f.exists() && f.isDirectory()) {
- /*
- * found a directory matching the name patterns. This
- * is a 1.4.2 hsperfdata_<user> directory. Check for
- * file named <lvmid> in that directory
- */
- String name = Integer.toString(lvmid);
- candidate = new File(f.getName(), name);
+ long newestTime = 0;
- } else if (f.exists() && f.isFile()) {
- /*
- * found a file matching the name patterns. This
- * is a 1.4.1 hsperfdata_<lvmid> file.
- */
- candidate = f;
+ for (String file : files) {
+ File f = new File(dir + file);
+ File candidate = null;
- } else {
- // unexpected - let conditional below filter this one out
- candidate = f;
- }
+ if (f.exists() && f.isDirectory()) {
+ /*
+ * found a directory matching the name patterns. This
+ * is a 1.4.2 hsperfdata_<user> directory. Check for
+ * file named <lvmid> in that directory
+ */
+ String name = f.getAbsolutePath() + File.separator + lvmid;
+ candidate = new File(name);
+ // Try NameSpace Id if Host Id doesn't exist.
+ if (!candidate.exists()) {
+ name = f.getAbsolutePath() + File.separator +
+ platSupport.getNamespaceVmId(lvmid);
+ candidate = new File(name);
+ }
+ } else if (f.exists() && f.isFile()) {
+ /*
+ * found a file matching the name patterns. This
+ * is a 1.4.1 hsperfdata_<lvmid> file.
+ */
+ candidate = f;
- if (candidate.exists() && candidate.isFile()
- && candidate.canRead()) {
- long modTime = candidate.lastModified();
- if (modTime >= newestTime) {
- newestTime = modTime;
- newest = candidate;
+ } else {
+ // unexpected - let conditional below filter this one out
+ candidate = f;
+ }
+
+ if (candidate.exists() && candidate.isFile()
+ && candidate.canRead()) {
+ long modTime = candidate.lastModified();
+ if (modTime >= newestTime) {
+ newestTime = modTime;
+ newest = candidate;
+ }
}
}
}
@@ -176,7 +190,7 @@ public class PerfDataFile {
* @return File - a File object to the backing store file for the named
* shared memory region of the target JVM.
* @see java.io.File
- * @see #getTempDirectory()
+ * @see #getTempDirectories()
*/
public static File getFile(String user, int lvmid) {
if (lvmid == 0) {
@@ -190,11 +204,22 @@ public class PerfDataFile {
}
// first try for 1.4.2 and later JVMs
- String basename = getTempDirectory(user) + Integer.toString(lvmid);
- File f = new File(basename);
+ List<String> tmpDirs = getTempDirectories(user, lvmid);
+ String basename;
+ File f;
- if (f.exists() && f.isFile() && f.canRead()) {
- return f;
+ for (String dir : tmpDirs) {
+ basename = dir + lvmid;
+ f = new File(basename);
+ if (f.exists() && f.isFile() && f.canRead()) {
+ return f;
+ }
+ // Try NameSpace Id if Host Id doesn't exist.
+ basename = dir + platSupport.getNamespaceVmId(lvmid);
+ f = new File(basename);
+ if (f.exists() && f.isFile() && f.canRead()) {
+ return f;
+ }
}
// No hit on 1.4.2 JVMs, try 1.4.1 files
@@ -235,7 +260,7 @@ public class PerfDataFile {
public static int getLocalVmId(File file) {
try {
// try 1.4.2 and later format first
- return Integer.parseInt(file.getName());
+ return(platSupport.getLocalVmId(file));
} catch (NumberFormatException e) { }
// now try the 1.4.1 format
@@ -266,7 +291,7 @@ public class PerfDataFile {
* @return String - the name of the temporary directory.
*/
public static String getTempDirectory() {
- return tmpDirName;
+ return PlatformSupport.getTemporaryDirectory();
}
/**
@@ -282,26 +307,28 @@ public class PerfDataFile {
* @return String - the name of the temporary directory.
*/
public static String getTempDirectory(String user) {
- return tmpDirName + dirNamePrefix + user + File.separator;
+ return getTempDirectory() + dirNamePrefix + user + File.separator;
}
- static {
- /*
- * For this to work, the target VM and this code need to use
- * the same directory. Instead of guessing which directory the
- * VM is using, we will ask.
- */
- String tmpdir = sun.misc.VMSupport.getVMTemporaryDirectory();
-
- /*
- * Assure that the string returned has a trailing File.separator
- * character. This check was added because the Linux implementation
- * changed such that the java.io.tmpdir string no longer terminates
- * with a File.separator character.
- */
- if (tmpdir.lastIndexOf(File.separator) != (tmpdir.length()-1)) {
- tmpdir = tmpdir + File.separator;
+ /**
+ * Return the names of the temporary directories being searched for
+ * HotSpot PerfData backing store files.
+ * <p>
+ * This method returns the traditional host temp directory but also
+ * includes a list of temp directories used by containers.
+ *
+ * @return List<String> - A List of temporary directories to search.
+ */
+ public static List<String> getTempDirectories(String userName, int vmid) {
+ List<String> list = platSupport.getTemporaryDirectories(vmid);
+ if (userName == null) {
+ return list;
}
- tmpDirName = tmpdir;
+
+ List<String> nameList = list.stream()
+ .map(name -> name + dirNamePrefix + userName + File.separator)
+ .collect(Collectors.toList());
+
+ return nameList;
}
}
--
2.22.0
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。