Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/tools/attach/HotSpotVirtualMachine.java
38918 views
/*1* Copyright (c) 2005, 2014, 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.attach;2627import com.sun.tools.attach.VirtualMachine;28import com.sun.tools.attach.AgentLoadException;29import com.sun.tools.attach.AgentInitializationException;30import com.sun.tools.attach.spi.AttachProvider;3132import java.io.InputStream;33import java.io.IOException;34import java.util.Properties;35import java.util.stream.Collectors;3637/*38* The HotSpot implementation of com.sun.tools.attach.VirtualMachine.39*/4041public abstract class HotSpotVirtualMachine extends VirtualMachine {4243HotSpotVirtualMachine(AttachProvider provider, String id) {44super(provider, id);45}4647/*48* Load agent library49* If isAbsolute is true then the agent library is the absolute path50* to the library and thus will not be expanded in the target VM.51* if isAbsolute is false then the agent library is just a library52* name and it will be expended in the target VM.53*/54private void loadAgentLibrary(String agentLibrary, boolean isAbsolute, String options)55throws AgentLoadException, AgentInitializationException, IOException56{57InputStream in = execute("load",58agentLibrary,59isAbsolute ? "true" : "false",60options);61try {62int result = readInt(in);63if (result != 0) {64throw new AgentInitializationException("Agent_OnAttach failed", result);65}66} finally {67in.close();6869}70}7172/*73* Load agent library - library name will be expanded in target VM74*/75public void loadAgentLibrary(String agentLibrary, String options)76throws AgentLoadException, AgentInitializationException, IOException77{78loadAgentLibrary(agentLibrary, false, options);79}8081/*82* Load agent - absolute path of library provided to target VM83*/84public void loadAgentPath(String agentLibrary, String options)85throws AgentLoadException, AgentInitializationException, IOException86{87loadAgentLibrary(agentLibrary, true, options);88}8990/*91* Load JPLIS agent which will load the agent JAR file and invoke92* the agentmain method.93*/94public void loadAgent(String agent, String options)95throws AgentLoadException, AgentInitializationException, IOException96{97String args = agent;98if (options != null) {99args = args + "=" + options;100}101try {102loadAgentLibrary("instrument", args);103} catch (AgentLoadException x) {104throw new InternalError("instrument library is missing in target VM", x);105} catch (AgentInitializationException x) {106/*107* Translate interesting errors into the right exception and108* message (FIXME: create a better interface to the instrument109* implementation so this isn't necessary)110*/111int rc = x.returnValue();112switch (rc) {113case JNI_ENOMEM:114throw new AgentLoadException("Insuffient memory");115case ATTACH_ERROR_BADJAR:116throw new AgentLoadException("Agent JAR not found or no Agent-Class attribute");117case ATTACH_ERROR_NOTONCP:118throw new AgentLoadException("Unable to add JAR file to system class path");119case ATTACH_ERROR_STARTFAIL:120throw new AgentInitializationException("Agent JAR loaded but agent failed to initialize");121default :122throw new AgentLoadException("Failed to load agent - unknown reason: " + rc);123}124}125}126127/*128* The possible errors returned by JPLIS's agentmain129*/130private static final int JNI_ENOMEM = -4;131private static final int ATTACH_ERROR_BADJAR = 100;132private static final int ATTACH_ERROR_NOTONCP = 101;133private static final int ATTACH_ERROR_STARTFAIL = 102;134135136/*137* Send "properties" command to target VM138*/139public Properties getSystemProperties() throws IOException {140InputStream in = null;141Properties props = new Properties();142try {143in = executeCommand("properties");144props.load(in);145} finally {146if (in != null) in.close();147}148return props;149}150151public Properties getAgentProperties() throws IOException {152InputStream in = null;153Properties props = new Properties();154try {155in = executeCommand("agentProperties");156props.load(in);157} finally {158if (in != null) in.close();159}160return props;161}162163private static final String MANAGMENT_PREFIX = "com.sun.management.";164165private static boolean checkedKeyName(Object key) {166if (!(key instanceof String)) {167throw new IllegalArgumentException("Invalid option (not a String): "+key);168}169if (!((String)key).startsWith(MANAGMENT_PREFIX)) {170throw new IllegalArgumentException("Invalid option: "+key);171}172return true;173}174175private static String stripKeyName(Object key) {176return ((String)key).substring(MANAGMENT_PREFIX.length());177}178179@Override180public void startManagementAgent(Properties agentProperties) throws IOException {181if (agentProperties == null) {182throw new NullPointerException("agentProperties cannot be null");183}184// Convert the arguments into arguments suitable for the Diagnostic Command:185// "ManagementAgent.start jmxremote.port=5555 jmxremote.authenticate=false"186String args = agentProperties.entrySet().stream()187.filter(entry -> checkedKeyName(entry.getKey()))188.map(entry -> stripKeyName(entry.getKey()) + "=" + escape(entry.getValue()))189.collect(Collectors.joining(" "));190executeJCmd("ManagementAgent.start " + args);191}192193private String escape(Object arg) {194String value = arg.toString();195if (value.contains(" ")) {196return "'" + value + "'";197}198return value;199}200201@Override202public String startLocalManagementAgent() throws IOException {203executeJCmd("ManagementAgent.start_local");204return getAgentProperties().getProperty("com.sun.management.jmxremote.localConnectorAddress");205}206207// --- HotSpot specific methods ---208209// same as SIGQUIT210public void localDataDump() throws IOException {211executeCommand("datadump").close();212}213214// Remote ctrl-break. The output of the ctrl-break actions can215// be read from the input stream.216public InputStream remoteDataDump(Object ... args) throws IOException {217return executeCommand("threaddump", args);218}219220// Remote heap dump. The output (error message) can be read from the221// returned input stream.222public InputStream dumpHeap(Object ... args) throws IOException {223return executeCommand("dumpheap", args);224}225226// Heap histogram (heap inspection in HotSpot)227public InputStream heapHisto(Object ... args) throws IOException {228return executeCommand("inspectheap", args);229}230231// set JVM command line flag232public InputStream setFlag(String name, String value) throws IOException {233return executeCommand("setflag", name, value);234}235236// print command line flag237public InputStream printFlag(String name) throws IOException {238return executeCommand("printflag", name);239}240241public InputStream executeJCmd(String command) throws IOException {242return executeCommand("jcmd", command);243}244245// -- Supporting methods246247248/*249* Execute the given command in the target VM - specific platform250* implementation must implement this.251*/252abstract InputStream execute(String cmd, Object ... args)253throws AgentLoadException, IOException;254255/*256* Convenience method for simple commands257*/258private InputStream executeCommand(String cmd, Object ... args) throws IOException {259try {260return execute(cmd, args);261} catch (AgentLoadException x) {262throw new InternalError("Should not get here", x);263}264}265266267/*268* Utility method to read an 'int' from the input stream. Ideally269* we should be using java.util.Scanner here but this implementation270* guarantees not to read ahead.271*/272int readInt(InputStream in) throws IOException {273StringBuilder sb = new StringBuilder();274275// read to \n or EOF276int n;277byte buf[] = new byte[1];278do {279n = in.read(buf, 0, 1);280if (n > 0) {281char c = (char)buf[0];282if (c == '\n') {283break; // EOL found284} else {285sb.append(c);286}287}288} while (n > 0);289290if (sb.length() == 0) {291throw new IOException("Premature EOF");292}293294int value;295try {296value = Integer.parseInt(sb.toString());297} catch (NumberFormatException x) {298throw new IOException("Non-numeric value found - int expected");299}300return value;301}302303/*304* Utility method to read data into a String.305*/306String readErrorMessage(InputStream sis) throws IOException {307byte b[] = new byte[1024];308int n;309StringBuffer message = new StringBuffer();310while ((n = sis.read(b)) != -1) {311message.append(new String(b, 0, n, "UTF-8"));312}313return message.toString();314}315316317// -- attach timeout support318319private static long defaultAttachTimeout = 5000;320private volatile long attachTimeout;321322/*323* Return attach timeout based on the value of the sun.tools.attach.attachTimeout324* property, or the default timeout if the property is not set to a positive325* value.326*/327long attachTimeout() {328if (attachTimeout == 0) {329synchronized(this) {330if (attachTimeout == 0) {331try {332String s =333System.getProperty("sun.tools.attach.attachTimeout");334attachTimeout = Long.parseLong(s);335} catch (SecurityException se) {336} catch (NumberFormatException ne) {337}338if (attachTimeout <= 0) {339attachTimeout = defaultAttachTimeout;340}341}342}343}344return attachTimeout;345}346}347348349