0N/A/*
4601N/A * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/Apackage sun.tools.attach;
0N/A
0N/Aimport com.sun.tools.attach.VirtualMachine;
0N/Aimport com.sun.tools.attach.AgentLoadException;
0N/Aimport com.sun.tools.attach.AgentInitializationException;
0N/Aimport com.sun.tools.attach.spi.AttachProvider;
0N/A
0N/Aimport java.io.InputStream;
0N/Aimport java.io.IOException;
0N/Aimport java.util.Properties;
0N/Aimport java.util.Map;
0N/A
0N/A/*
0N/A * The HotSpot implementation of com.sun.tools.attach.VirtualMachine.
0N/A */
0N/A
0N/Apublic abstract class HotSpotVirtualMachine extends VirtualMachine {
0N/A
0N/A HotSpotVirtualMachine(AttachProvider provider, String id) {
0N/A super(provider, id);
0N/A }
0N/A
0N/A /*
0N/A * Load agent library
0N/A * If isAbsolute is true then the agent library is the absolute path
0N/A * to the library and thus will not be expanded in the target VM.
0N/A * if isAbsolute is false then the agent library is just a library
0N/A * name and it will be expended in the target VM.
0N/A */
0N/A private void loadAgentLibrary(String agentLibrary, boolean isAbsolute, String options)
0N/A throws AgentLoadException, AgentInitializationException, IOException
0N/A {
0N/A InputStream in = execute("load",
0N/A agentLibrary,
0N/A isAbsolute ? "true" : "false",
0N/A options);
0N/A try {
0N/A int result = readInt(in);
0N/A if (result != 0) {
0N/A throw new AgentInitializationException("Agent_OnAttach failed", result);
0N/A }
0N/A } finally {
0N/A in.close();
0N/A
0N/A }
0N/A }
0N/A
0N/A /*
0N/A * Load agent library - library name will be expanded in target VM
0N/A */
0N/A public void loadAgentLibrary(String agentLibrary, String options)
0N/A throws AgentLoadException, AgentInitializationException, IOException
0N/A {
0N/A loadAgentLibrary(agentLibrary, false, options);
0N/A }
0N/A
0N/A /*
0N/A * Load agent - absolute path of library provided to target VM
0N/A */
0N/A public void loadAgentPath(String agentLibrary, String options)
0N/A throws AgentLoadException, AgentInitializationException, IOException
0N/A {
0N/A loadAgentLibrary(agentLibrary, true, options);
0N/A }
0N/A
0N/A /*
0N/A * Load JPLIS agent which will load the agent JAR file and invoke
0N/A * the agentmain method.
0N/A */
0N/A public void loadAgent(String agent, String options)
0N/A throws AgentLoadException, AgentInitializationException, IOException
0N/A {
0N/A String args = agent;
0N/A if (options != null) {
0N/A args = args + "=" + options;
0N/A }
0N/A try {
0N/A loadAgentLibrary("instrument", args);
0N/A } catch (AgentLoadException x) {
0N/A throw new InternalError("instrument library is missing in target VM");
0N/A } catch (AgentInitializationException x) {
0N/A /*
0N/A * Translate interesting errors into the right exception and
0N/A * message (FIXME: create a better interface to the instrument
0N/A * implementation so this isn't necessary)
0N/A */
0N/A int rc = x.returnValue();
0N/A switch (rc) {
0N/A case JNI_ENOMEM:
0N/A throw new AgentLoadException("Insuffient memory");
0N/A case ATTACH_ERROR_BADJAR:
0N/A throw new AgentLoadException("Agent JAR not found or no Agent-Class attribute");
0N/A case ATTACH_ERROR_NOTONCP:
0N/A throw new AgentLoadException("Unable to add JAR file to system class path");
0N/A case ATTACH_ERROR_STARTFAIL:
0N/A throw new AgentInitializationException("Agent JAR loaded but agent failed to initialize");
0N/A default :
0N/A throw new AgentLoadException("Failed to load agent - unknown reason: " + rc);
0N/A }
0N/A }
0N/A }
0N/A
0N/A /*
0N/A * The possible errors returned by JPLIS's agentmain
0N/A */
0N/A private static final int JNI_ENOMEM = -4;
0N/A private static final int ATTACH_ERROR_BADJAR = 100;
0N/A private static final int ATTACH_ERROR_NOTONCP = 101;
0N/A private static final int ATTACH_ERROR_STARTFAIL = 102;
0N/A
0N/A
0N/A /*
0N/A * Send "properties" command to target VM
0N/A */
0N/A public Properties getSystemProperties() throws IOException {
0N/A InputStream in = null;
0N/A Properties props = new Properties();
0N/A try {
0N/A in = executeCommand("properties");
0N/A props.load(in);
0N/A } finally {
0N/A if (in != null) in.close();
0N/A }
0N/A return props;
0N/A }
0N/A
0N/A public Properties getAgentProperties() throws IOException {
0N/A InputStream in = null;
0N/A Properties props = new Properties();
0N/A try {
0N/A in = executeCommand("agentProperties");
0N/A props.load(in);
0N/A } finally {
0N/A if (in != null) in.close();
0N/A }
0N/A return props;
0N/A }
0N/A
0N/A // --- HotSpot specific methods ---
0N/A
0N/A // same as SIGQUIT
0N/A public void localDataDump() throws IOException {
0N/A executeCommand("datadump").close();
0N/A }
0N/A
0N/A // Remote ctrl-break. The output of the ctrl-break actions can
0N/A // be read from the input stream.
0N/A public InputStream remoteDataDump(Object ... args) throws IOException {
0N/A return executeCommand("threaddump", args);
0N/A }
0N/A
0N/A // Remote heap dump. The output (error message) can be read from the
0N/A // returned input stream.
0N/A public InputStream dumpHeap(Object ... args) throws IOException {
0N/A return executeCommand("dumpheap", args);
0N/A }
0N/A
0N/A // Heap histogram (heap inspection in HotSpot)
0N/A public InputStream heapHisto(Object ... args) throws IOException {
0N/A return executeCommand("inspectheap", args);
0N/A }
0N/A
0N/A // set JVM command line flag
0N/A public InputStream setFlag(String name, String value) throws IOException {
0N/A return executeCommand("setflag", name, value);
0N/A }
0N/A
0N/A // print command line flag
0N/A public InputStream printFlag(String name) throws IOException {
0N/A return executeCommand("printflag", name);
0N/A }
0N/A
4601N/A public InputStream executeJCmd(String command) throws IOException {
4601N/A return executeCommand("jcmd", command);
4601N/A }
4601N/A
0N/A // -- Supporting methods
0N/A
0N/A
0N/A /*
0N/A * Execute the given command in the target VM - specific platform
0N/A * implementation must implement this.
0N/A */
0N/A abstract InputStream execute(String cmd, Object ... args)
0N/A throws AgentLoadException, IOException;
0N/A
0N/A /*
0N/A * Convenience method for simple commands
0N/A */
0N/A private InputStream executeCommand(String cmd, Object ... args) throws IOException {
0N/A try {
0N/A return execute(cmd, args);
0N/A } catch (AgentLoadException x) {
0N/A throw new InternalError("Should not get here");
0N/A }
0N/A }
0N/A
0N/A
0N/A /*
0N/A * Utility method to read an 'int' from the input stream. Ideally
0N/A * we should be using java.util.Scanner here but this implementation
0N/A * guarantees not to read ahead.
0N/A */
0N/A int readInt(InputStream in) throws IOException {
0N/A StringBuilder sb = new StringBuilder();
0N/A
0N/A // read to \n or EOF
0N/A int n;
0N/A byte buf[] = new byte[1];
0N/A do {
0N/A n = in.read(buf, 0, 1);
0N/A if (n > 0) {
0N/A char c = (char)buf[0];
0N/A if (c == '\n') {
0N/A break; // EOL found
0N/A } else {
0N/A sb.append(c);
0N/A }
0N/A }
0N/A } while (n > 0);
0N/A
0N/A if (sb.length() == 0) {
0N/A throw new IOException("Premature EOF");
0N/A }
0N/A
0N/A int value;
0N/A try {
0N/A value = Integer.parseInt(sb.toString());
0N/A } catch (NumberFormatException x) {
0N/A throw new IOException("Non-numeric value found - int expected");
0N/A }
0N/A return value;
0N/A }
0N/A
0N/A // -- attach timeout support
0N/A
0N/A private static long defaultAttachTimeout = 5000;
0N/A private volatile long attachTimeout;
0N/A
0N/A /*
0N/A * Return attach timeout based on the value of the sun.tools.attach.attachTimeout
0N/A * property, or the default timeout if the property is not set to a positive
0N/A * value.
0N/A */
0N/A long attachTimeout() {
0N/A if (attachTimeout == 0) {
0N/A synchronized(this) {
0N/A if (attachTimeout == 0) {
0N/A try {
0N/A String s =
0N/A System.getProperty("sun.tools.attach.attachTimeout");
0N/A attachTimeout = Long.parseLong(s);
0N/A } catch (SecurityException se) {
0N/A } catch (NumberFormatException ne) {
0N/A }
0N/A if (attachTimeout <= 0) {
0N/A attachTimeout = defaultAttachTimeout;
0N/A }
0N/A }
0N/A }
0N/A }
0N/A return attachTimeout;
0N/A }
0N/A}