Path: blob/master/src/jdk.attach/share/classes/com/sun/tools/attach/VirtualMachine.java
40948 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 com.sun.tools.attach;2627import com.sun.tools.attach.spi.AttachProvider;28import java.util.ArrayList;29import java.util.List;30import java.util.Properties;31import java.io.IOException;323334/**35* A Java virtual machine.36*37* <p> A {@code VirtualMachine} represents a Java virtual machine to which this38* Java virtual machine has attached. The Java virtual machine to which it is39* attached is sometimes called the <i>target virtual machine</i>, or <i>target VM</i>.40* An application (typically a tool such as a managemet console or profiler) uses a41* VirtualMachine to load an agent into the target VM. For example, a profiler tool42* written in the Java Language might attach to a running application and load its43* profiler agent to profile the running application. </p>44*45* <p> A VirtualMachine is obtained by invoking the {@link #attach(String) attach} method46* with an identifier that identifies the target virtual machine. The identifier is47* implementation-dependent but is typically the process identifier (or pid) in48* environments where each Java virtual machine runs in its own operating system process.49* Alternatively, a {@code VirtualMachine} instance is obtained by invoking the50* {@link #attach(VirtualMachineDescriptor) attach} method with a {@link51* com.sun.tools.attach.VirtualMachineDescriptor VirtualMachineDescriptor} obtained52* from the list of virtual machine descriptors returned by the {@link #list list} method.53* Once a reference to a virtual machine is obtained, the {@link #loadAgent loadAgent},54* {@link #loadAgentLibrary loadAgentLibrary}, and {@link #loadAgentPath loadAgentPath}55* methods are used to load agents into target virtual machine. The {@link56* #loadAgent loadAgent} method is used to load agents that are written in the Java57* Language and deployed in a {@link java.util.jar.JarFile JAR file}. (See58* {@link java.lang.instrument} for a detailed description on how these agents59* are loaded and started). The {@link #loadAgentLibrary loadAgentLibrary} and60* {@link #loadAgentPath loadAgentPath} methods are used to load agents that61* are deployed either in a dynamic library or statically linked into the VM and62* make use of the <a href="{@docRoot}/../specs/jvmti.html">JVM Tools Interface</a>.63* </p>64*65* <p> In addition to loading agents a VirtualMachine provides read access to the66* {@link java.lang.System#getProperties() system properties} in the target VM.67* This can be useful in some environments where properties such as68* {@code java.home}, {@code os.name}, or {@code os.arch} are69* used to construct the path to agent that will be loaded into the target VM.70*71* <p> The following example demonstrates how VirtualMachine may be used:</p>72*73* <pre>74*75* // attach to target VM76* VirtualMachine vm = VirtualMachine.attach("2177");77*78* // start management agent79* Properties props = new Properties();80* props.put("com.sun.management.jmxremote.port", "5000");81* vm.startManagementAgent(props);82*83* // detach84* vm.detach();85*86* </pre>87*88* <p> In this example we attach to a Java virtual machine that is identified by89* the process identifier {@code 2177}. Then the JMX management agent is90* started in the target process using the supplied arguments. Finally, the91* client detaches from the target VM. </p>92*93* <p> A VirtualMachine is safe for use by multiple concurrent threads. </p>94*95* @since 1.696*/9798public abstract class VirtualMachine {99private AttachProvider provider;100private String id;101private volatile int hash; // 0 => not computed102103/**104* Initializes a new instance of this class.105*106* @param provider107* The attach provider creating this class.108* @param id109* The abstract identifier that identifies the Java virtual machine.110*111* @throws NullPointerException112* If {@code provider} or {@code id} is {@code null}.113*/114protected VirtualMachine(AttachProvider provider, String id) {115if (provider == null) {116throw new NullPointerException("provider cannot be null");117}118if (id == null) {119throw new NullPointerException("id cannot be null");120}121this.provider = provider;122this.id = id;123}124125/**126* Return a list of Java virtual machines.127*128* <p> This method returns a list of Java {@link129* com.sun.tools.attach.VirtualMachineDescriptor} elements.130* The list is an aggregation of the virtual machine131* descriptor lists obtained by invoking the {@link132* com.sun.tools.attach.spi.AttachProvider#listVirtualMachines133* listVirtualMachines} method of all installed134* {@link com.sun.tools.attach.spi.AttachProvider attach providers}.135* If there are no Java virtual machines known to any provider136* then an empty list is returned.137*138* @return The list of virtual machine descriptors.139*/140public static List<VirtualMachineDescriptor> list() {141ArrayList<VirtualMachineDescriptor> l =142new ArrayList<VirtualMachineDescriptor>();143List<AttachProvider> providers = AttachProvider.providers();144for (AttachProvider provider: providers) {145l.addAll(provider.listVirtualMachines());146}147return l;148}149150/**151* Attaches to a Java virtual machine.152*153* <p> This method obtains the list of attach providers by invoking the154* {@link com.sun.tools.attach.spi.AttachProvider#providers()155* AttachProvider.providers()} method. It then iterates overs the list156* and invokes each provider's {@link157* com.sun.tools.attach.spi.AttachProvider#attachVirtualMachine(java.lang.String)158* attachVirtualMachine} method in turn. If a provider successfully159* attaches then the iteration terminates, and the VirtualMachine created160* by the provider that successfully attached is returned by this method.161* If the {@code attachVirtualMachine} method of all providers throws162* {@link com.sun.tools.attach.AttachNotSupportedException AttachNotSupportedException}163* then this method also throws {@code AttachNotSupportedException}.164* This means that {@code AttachNotSupportedException} is thrown when165* the identifier provided to this method is invalid, or the identifier166* corresponds to a Java virtual machine that does not exist, or none167* of the providers can attach to it. This exception is also thrown if168* {@link com.sun.tools.attach.spi.AttachProvider#providers()169* AttachProvider.providers()} returns an empty list. </p>170*171* @param id172* The abstract identifier that identifies the Java virtual machine.173*174* @return A VirtualMachine representing the target VM.175*176* @throws SecurityException177* If a security manager has been installed and it denies178* {@link com.sun.tools.attach.AttachPermission AttachPermission}179* {@code ("attachVirtualMachine")}, or another permission180* required by the implementation.181*182* @throws AttachNotSupportedException183* If the {@code attachVirtualmachine} method of all installed184* providers throws {@code AttachNotSupportedException}, or185* there aren't any providers installed.186*187* @throws IOException188* If an I/O error occurs189*190* @throws NullPointerException191* If {@code id} is {@code null}.192*/193public static VirtualMachine attach(String id)194throws AttachNotSupportedException, IOException195{196if (id == null) {197throw new NullPointerException("id cannot be null");198}199List<AttachProvider> providers = AttachProvider.providers();200if (providers.size() == 0) {201throw new AttachNotSupportedException("no providers installed");202}203AttachNotSupportedException lastExc = null;204for (AttachProvider provider: providers) {205try {206return provider.attachVirtualMachine(id);207} catch (AttachNotSupportedException x) {208lastExc = x;209}210}211throw lastExc;212}213214/**215* Attaches to a Java virtual machine.216*217* <p> This method first invokes the {@link218* com.sun.tools.attach.VirtualMachineDescriptor#provider() provider()} method219* of the given virtual machine descriptor to obtain the attach provider. It220* then invokes the attach provider's {@link221* com.sun.tools.attach.spi.AttachProvider#attachVirtualMachine(VirtualMachineDescriptor)222* attachVirtualMachine} to attach to the target VM.223*224* @param vmd225* The virtual machine descriptor.226*227* @return A VirtualMachine representing the target VM.228*229* @throws SecurityException230* If a security manager has been installed and it denies231* {@link com.sun.tools.attach.AttachPermission AttachPermission}232* {@code ("attachVirtualMachine")}, or another permission233* required by the implementation.234*235* @throws AttachNotSupportedException236* If the attach provider's {@code attachVirtualmachine}237* throws {@code AttachNotSupportedException}.238*239* @throws IOException240* If an I/O error occurs241*242* @throws NullPointerException243* If {@code vmd} is {@code null}.244*/245public static VirtualMachine attach(VirtualMachineDescriptor vmd)246throws AttachNotSupportedException, IOException247{248return vmd.provider().attachVirtualMachine(vmd);249}250251/**252* Detach from the virtual machine.253*254* <p> After detaching from the virtual machine, any further attempt to invoke255* operations on that virtual machine will cause an {@link java.io.IOException256* IOException} to be thrown. If an operation (such as {@link #loadAgent257* loadAgent} for example) is in progress when this method is invoked then258* the behaviour is implementation dependent. In other words, it is259* implementation specific if the operation completes or throws260* {@code IOException}.261*262* <p> If already detached from the virtual machine then invoking this263* method has no effect. </p>264*265* @throws IOException266* If an I/O error occurs267*/268public abstract void detach() throws IOException;269270/**271* Returns the provider that created this virtual machine.272*273* @return The provider that created this virtual machine.274*/275public final AttachProvider provider() {276return provider;277}278279/**280* Returns the identifier for this Java virtual machine.281*282* @return The identifier for this Java virtual machine.283*/284public final String id() {285return id;286}287288/**289* Loads an agent library.290*291* <p> A <a href="{@docRoot}/../specs/jvmti.html">JVM TI</a>292* client is called an <i>agent</i>. It is developed in a native language.293* A JVM TI agent is deployed in a platform specific manner but it is typically the294* platform equivalent of a dynamic library. Alternatively, it may be statically linked into the VM.295* This method causes the given agent library to be loaded into the target296* VM (if not already loaded or if not statically linked into the VM).297* It then causes the target VM to invoke the {@code Agent_OnAttach} function298* or, for a statically linked agent named 'L', the {@code Agent_OnAttach_L} function299* as specified in the300* <a href="{@docRoot}/../specs/jvmti.html">JVM Tools Interface</a> specification.301* Note that the {@code Agent_OnAttach[_L]}302* function is invoked even if the agent library was loaded prior to invoking303* this method.304*305* <p> The agent library provided is the name of the agent library. It is interpreted306* in the target virtual machine in an implementation-dependent manner. Typically an307* implementation will expand the library name into an operating system specific file308* name. For example, on UNIX systems, the name {@code L} might be expanded to309* {@code libL.so}, and located using the search path specified by the310* {@code LD_LIBRARY_PATH} environment variable. If the agent named 'L' is311* statically linked into the VM then the VM must export a function named312* {@code Agent_OnAttach_L}.</p>313*314* <p> If the {@code Agent_OnAttach[_L]} function in the agent library returns315* an error then an {@link com.sun.tools.attach.AgentInitializationException} is316* thrown. The return value from the {@code Agent_OnAttach[_L]} can then be317* obtained by invoking the {@link318* com.sun.tools.attach.AgentInitializationException#returnValue() returnValue}319* method on the exception. </p>320*321* @param agentLibrary322* The name of the agent library.323*324* @param options325* The options to provide to the {@code Agent_OnAttach[_L]}326* function (can be {@code null}).327*328* @throws AgentLoadException329* If the agent library does not exist, the agent library is not330* statically linked with the VM, or the agent library cannot be331* loaded for another reason.332*333* @throws AgentInitializationException334* If the {@code Agent_OnAttach[_L]} function returns an error.335*336* @throws IOException337* If an I/O error occurs338*339* @throws NullPointerException340* If {@code agentLibrary} is {@code null}.341*342* @see com.sun.tools.attach.AgentInitializationException#returnValue()343*/344public abstract void loadAgentLibrary(String agentLibrary, String options)345throws AgentLoadException, AgentInitializationException, IOException;346347/**348* Loads an agent library.349*350* <p> This convenience method works as if by invoking:351*352* <blockquote><code>353* {@link #loadAgentLibrary(String, String) loadAgentLibrary}(agentLibrary, null);354* </code></blockquote>355*356* @param agentLibrary357* The name of the agent library.358*359* @throws AgentLoadException360* If the agent library does not exist, the agent library is not361* statically linked with the VM, or the agent library cannot be362* loaded for another reason.363*364* @throws AgentInitializationException365* If the {@code Agent_OnAttach[_L]} function returns an error.366*367* @throws IOException368* If an I/O error occurs369*370* @throws NullPointerException371* If {@code agentLibrary} is {@code null}.372*/373public void loadAgentLibrary(String agentLibrary)374throws AgentLoadException, AgentInitializationException, IOException375{376loadAgentLibrary(agentLibrary, null);377}378379/**380* Load a native agent library by full pathname.381*382* <p> A <a href="{@docRoot}/../specs/jvmti.html">JVM TI</a>383* client is called an <i>agent</i>. It is developed in a native language.384* A JVM TI agent is deployed in a platform specific manner but it is typically the385* platform equivalent of a dynamic library. Alternatively, the native386* library specified by the agentPath parameter may be statically387* linked with the VM. The parsing of the agentPath parameter into388* a statically linked library name is done in a platform389* specific manner in the VM. For example, in UNIX, an agentPath parameter390* of {@code /a/b/libL.so} would name a library 'L'.391*392* See the JVM TI Specification for more details.393*394* This method causes the given agent library to be loaded into the target395* VM (if not already loaded or if not statically linked into the VM).396* It then causes the target VM to invoke the {@code Agent_OnAttach}397* function or, for a statically linked agent named 'L', the398* {@code Agent_OnAttach_L} function as specified in the399* <a href="{@docRoot}/../specs/jvmti.html">JVM Tools Interface</a> specification.400* Note that the {@code Agent_OnAttach[_L]}401* function is invoked even if the agent library was loaded prior to invoking402* this method.403*404* <p> The agent library provided is the absolute path from which to load the405* agent library. Unlike {@link #loadAgentLibrary loadAgentLibrary}, the library name406* is not expanded in the target virtual machine. </p>407*408* <p> If the {@code Agent_OnAttach[_L]} function in the agent library returns409* an error then an {@link com.sun.tools.attach.AgentInitializationException} is410* thrown. The return value from the {@code Agent_OnAttach[_L]} can then be411* obtained by invoking the {@link412* com.sun.tools.attach.AgentInitializationException#returnValue() returnValue}413* method on the exception. </p>414*415* @param agentPath416* The full path of the agent library.417*418* @param options419* The options to provide to the {@code Agent_OnAttach[_L]}420* function (can be {@code null}).421*422* @throws AgentLoadException423* If the agent library does not exist, the agent library is not424* statically linked with the VM, or the agent library cannot be425* loaded for another reason.426*427* @throws AgentInitializationException428* If the {@code Agent_OnAttach[_L]} function returns an error.429*430* @throws IOException431* If an I/O error occurs432*433* @throws NullPointerException434* If {@code agentPath} is {@code null}.435*436* @see com.sun.tools.attach.AgentInitializationException#returnValue()437*/438public abstract void loadAgentPath(String agentPath, String options)439throws AgentLoadException, AgentInitializationException, IOException;440441/**442* Load a native agent library by full pathname.443*444* <p> This convenience method works as if by invoking:445*446* <blockquote><code>447* {@link #loadAgentPath(String, String) loadAgentPath}(agentLibrary, null);448* </code></blockquote>449*450* @param agentPath451* The full path to the agent library.452*453* @throws AgentLoadException454* If the agent library does not exist, the agent library is not455* statically linked with the VM, or the agent library cannot be456* loaded for another reason.457*458* @throws AgentInitializationException459* If the {@code Agent_OnAttach[_L]} function returns an error.460*461* @throws IOException462* If an I/O error occurs463*464* @throws NullPointerException465* If {@code agentPath} is {@code null}.466*/467public void loadAgentPath(String agentPath)468throws AgentLoadException, AgentInitializationException, IOException469{470loadAgentPath(agentPath, null);471}472473474/**475* Loads an agent.476*477* <p> The agent provided to this method is a path name to a JAR file on the file478* system of the target virtual machine. This path is passed to the target virtual479* machine where it is interpreted. The target virtual machine attempts to start480* the agent as specified by the {@link java.lang.instrument} specification.481* That is, the specified JAR file is added to the system class path (of the target482* virtual machine), and the {@code agentmain} method of the agent class, specified483* by the {@code Agent-Class} attribute in the JAR manifest, is invoked. This484* method completes when the {@code agentmain} method completes.485*486* @param agent487* Path to the JAR file containing the agent.488*489* @param options490* The options to provide to the agent's {@code agentmain}491* method (can be {@code null}).492*493* @throws AgentLoadException494* If the agent does not exist, or cannot be started in the manner495* specified in the {@link java.lang.instrument} specification.496*497* @throws AgentInitializationException498* If the {@code agentmain} throws an exception499*500* @throws IOException501* If an I/O error occurs502*503* @throws NullPointerException504* If {@code agent} is {@code null}.505*/506public abstract void loadAgent(String agent, String options)507throws AgentLoadException, AgentInitializationException, IOException;508509/**510* Loads an agent.511*512* <p> This convenience method works as if by invoking:513*514* <blockquote><code>515* {@link #loadAgent(String, String) loadAgent}(agent, null);516* </code></blockquote>517*518* @param agent519* Path to the JAR file containing the agent.520*521* @throws AgentLoadException522* If the agent does not exist, or cannot be started in the manner523* specified in the {@link java.lang.instrument} specification.524*525* @throws AgentInitializationException526* If the {@code agentmain} throws an exception527*528* @throws IOException529* If an I/O error occurs530*531* @throws NullPointerException532* If {@code agent} is {@code null}.533*/534public void loadAgent(String agent)535throws AgentLoadException, AgentInitializationException, IOException536{537loadAgent(agent, null);538}539540/**541* Returns the current system properties in the target virtual machine.542*543* <p> This method returns the system properties in the target virtual544* machine. Properties whose key or value is not a {@code String} are545* omitted. The method is approximately equivalent to the invocation of the546* method {@link java.lang.System#getProperties System.getProperties}547* in the target virtual machine except that properties with a key or548* value that is not a {@code String} are not included.549*550* <p> This method is typically used to decide which agent to load into551* the target virtual machine with {@link #loadAgent loadAgent}, or552* {@link #loadAgentLibrary loadAgentLibrary}. For example, the553* {@code java.home} or {@code user.dir} properties might be554* use to create the path to the agent library or JAR file.555*556* @return The system properties557*558* @throws AttachOperationFailedException559* If the target virtual machine is unable to complete the560* attach operation. A more specific error message will be561* given by {@link AttachOperationFailedException#getMessage()}.562*563* @throws IOException564* If an I/O error occurs, a communication error for example,565* that cannot be identified as an error to indicate that the566* operation failed in the target VM.567*568* @see java.lang.System#getProperties569* @see #loadAgentLibrary570* @see #loadAgent571*/572public abstract Properties getSystemProperties() throws IOException;573574/**575* Returns the current <i>agent properties</i> in the target virtual576* machine.577*578* <p> The target virtual machine can maintain a list of properties on579* behalf of agents. The manner in which this is done, the names of the580* properties, and the types of values that are allowed, is implementation581* specific. Agent properties are typically used to store communication582* end-points and other agent configuration details. For example, a debugger583* agent might create an agent property for its transport address.584*585* <p> This method returns the agent properties whose key and value is a586* {@code String}. Properties whose key or value is not a {@code String}587* are omitted. If there are no agent properties maintained in the target588* virtual machine then an empty property list is returned.589*590* @return The agent properties591*592* @throws AttachOperationFailedException593* If the target virtual machine is unable to complete the594* attach operation. A more specific error message will be595* given by {@link AttachOperationFailedException#getMessage()}.596*597* @throws IOException598* If an I/O error occurs, a communication error for example,599* that cannot be identified as an error to indicate that the600* operation failed in the target VM.601*/602public abstract Properties getAgentProperties() throws IOException;603604/**605* Starts the JMX management agent in the target virtual machine.606*607* <p> The configuration properties are the same as those specified on608* the command line when starting the JMX management agent. In the same609* way as on the command line, you need to specify at least the610* {@code com.sun.management.jmxremote.port} property.611*612* <p> See the online documentation for613* {@extLink monitoring_and_management_using_jmx_technology614* Monitoring and Management Using JMX Technology} for further details.615*616* @param agentProperties617* A Properties object containing the configuration properties618* for the agent.619*620* @throws AttachOperationFailedException621* If the target virtual machine is unable to complete the622* attach operation. A more specific error message will be623* given by {@link AttachOperationFailedException#getMessage()}.624*625* @throws IOException626* If an I/O error occurs, a communication error for example,627* that cannot be identified as an error to indicate that the628* operation failed in the target VM.629*630* @throws IllegalArgumentException631* If keys or values in agentProperties are invalid.632*633* @throws NullPointerException634* If agentProperties is null.635*636* @since 1.8637*/638public abstract void startManagementAgent(Properties agentProperties) throws IOException;639640/**641* Starts the local JMX management agent in the target virtual machine.642*643* <p> See the online documentation for644* {@extLink monitoring_and_management_using_jmx_technology645* Monitoring and Management Using JMX Technology} for further details.646*647* @return The String representation of the local connector's service address.648* The value can be parsed by the649* {@link javax.management.remote.JMXServiceURL#JMXServiceURL(String)}650* constructor.651*652* @throws AttachOperationFailedException653* If the target virtual machine is unable to complete the654* attach operation. A more specific error message will be655* given by {@link AttachOperationFailedException#getMessage()}.656*657* @throws IOException658* If an I/O error occurs, a communication error for example,659* that cannot be identified as an error to indicate that the660* operation failed in the target VM.661*662* @since 1.8663*/664public abstract String startLocalManagementAgent() throws IOException;665666/**667* Returns a hash-code value for this VirtualMachine. The hash668* code is based upon the VirtualMachine's components, and satifies669* the general contract of the {@link java.lang.Object#hashCode()670* Object.hashCode} method.671*672* @return A hash-code value for this virtual machine673*/674public int hashCode() {675if (hash != 0) {676return hash;677}678hash = provider.hashCode() * 127 + id.hashCode();679return hash;680}681682/**683* Tests this VirtualMachine for equality with another object.684*685* <p> If the given object is not a VirtualMachine then this686* method returns {@code false}. For two VirtualMachines to687* be considered equal requires that they both reference the same688* provider, and their {@link VirtualMachineDescriptor#id() identifiers} are equal. </p>689*690* <p> This method satisfies the general contract of the {@link691* java.lang.Object#equals(Object) Object.equals} method. </p>692*693* @param ob The object to which this object is to be compared694*695* @return {@code true} if, and only if, the given object is696* a VirtualMachine that is equal to this697* VirtualMachine.698*/699public boolean equals(Object ob) {700if (ob == this)701return true;702if (!(ob instanceof VirtualMachine))703return false;704VirtualMachine other = (VirtualMachine)ob;705if (other.provider() != this.provider()) {706return false;707}708if (!other.id().equals(this.id())) {709return false;710}711return true;712}713714/**715* Returns the string representation of the {@code VirtualMachine}.716*/717public String toString() {718return provider.toString() + ": " + id;719}720}721722723