Path: blob/master/src/jdk.jcmd/share/classes/sun/tools/common/ProcessArgumentMatcher.java
41159 views
/*1* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.tools.common;2627import java.net.URISyntaxException;28import java.util.ArrayList;29import java.util.Collection;30import java.util.List;31import java.util.stream.Collectors;3233import com.sun.tools.attach.VirtualMachine;34import com.sun.tools.attach.VirtualMachineDescriptor;3536import sun.jvmstat.monitor.MonitorException;37import sun.jvmstat.monitor.MonitoredHost;38import sun.jvmstat.monitor.MonitoredVm;39import sun.jvmstat.monitor.MonitoredVmUtil;40import sun.jvmstat.monitor.VmIdentifier;4142/**43* Class for finding process matching a process argument,44* excluding tool it self and returning a list containing45* the process identifiers.46*/47public class ProcessArgumentMatcher {48private String matchClass;49private String singlePid;5051public ProcessArgumentMatcher(String pidArg) {52if (pidArg == null || pidArg.isEmpty()) {53throw new IllegalArgumentException("Pid string is invalid");54}55if (pidArg.charAt(0) == '-') {56throw new IllegalArgumentException("Unrecognized " + pidArg);57}58try {59long pid = Long.parseLong(pidArg);60if (pid != 0) {61singlePid = String.valueOf(pid);62}63} catch (NumberFormatException nfe) {64matchClass = pidArg;65}66}6768private static String getExcludeStringFrom(Class<?> excludeClass) {69if (excludeClass == null) {70return "";71}72Module m = excludeClass.getModule();73if (m.isNamed()) {74return m.getName() + "/" + excludeClass.getName();75}76return excludeClass.getName();77}7879private static boolean check(VirtualMachineDescriptor vmd, String excludeClass, String partialMatch) {8081// Try to get the main class name using (platform specific) ProcessHelper82String mainClass = ProcessHelper.getMainClass(vmd.id());8384// If the main class name could not be retrieved by ProcessHelper, get it with the attach mechanism85if (mainClass == null) {86try {87VmIdentifier vmId = new VmIdentifier(vmd.id());88MonitoredHost monitoredHost = MonitoredHost.getMonitoredHost(vmId);89MonitoredVm monitoredVm = monitoredHost.getMonitoredVm(vmId, -1);90mainClass = MonitoredVmUtil.mainClass(monitoredVm, true);91monitoredHost.detach(monitoredVm);92} catch (NullPointerException npe) {93// There is a potential race, where a running java app is being94// queried, unfortunately the java app has shutdown after this95// method is started but before getMonitoredVM is called.96// If this is the case, then the /tmp/hsperfdata_xxx/pid file97// will have disappeared and we will get a NullPointerException.98// Handle this gracefully....99return false;100} catch (MonitorException | URISyntaxException e) {101return false;102}103}104105106if (excludeClass != null && mainClass.equals(excludeClass)) {107return false;108}109110if (partialMatch != null && mainClass.indexOf(partialMatch) == -1) {111return false;112}113114return true;115}116117private static Collection<VirtualMachineDescriptor> getSingleVMD(String pid) {118Collection<VirtualMachineDescriptor> vids = new ArrayList<>();119List<VirtualMachineDescriptor> vmds = VirtualMachine.list();120for (VirtualMachineDescriptor vmd : vmds) {121if (check(vmd, null, null)) {122if (pid.equals(vmd.id())) {123vids.add(vmd);124}125}126}127return vids;128}129130private static Collection<VirtualMachineDescriptor> getVMDs(Class<?> excludeClass, String partialMatch) {131String excludeCls = getExcludeStringFrom(excludeClass);132Collection<VirtualMachineDescriptor> vids = new ArrayList<>();133List<VirtualMachineDescriptor> vmds = VirtualMachine.list();134for (VirtualMachineDescriptor vmd : vmds) {135if (check(vmd, excludeCls, partialMatch)) {136vids.add(vmd);137}138}139return vids;140}141142public Collection<VirtualMachineDescriptor> getVirtualMachineDescriptors() {143if (singlePid != null) {144return getSingleVMD(singlePid);145} else {146return getVMDs(null, matchClass);147}148}149150public Collection<String> getVirtualMachinePids(Class<?> excludeClass) {151if (singlePid != null) {152// There is a bug in AttachProvider, when VM is debuggee-suspended it's not listed by the AttachProvider.153// If we are talking about a specific pid, just return it.154return List.of(singlePid);155} else {156return getVMDs(excludeClass, matchClass).stream().map(x -> {return x.id();}).collect(Collectors.toList());157}158}159160}161162163