/*
* Copyright (c) 1998, 2017, 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 com.sun.jdi;
import java.io.IOException;
import java.util.List;
import com.sun.jdi.connect.AttachingConnector;
import com.sun.jdi.connect.Connector;
import com.sun.jdi.connect.LaunchingConnector;
import com.sun.jdi.connect.ListeningConnector;
import com.sun.jdi.connect.Transport;
import com.sun.jdi.connect.spi.Connection;
import com.sun.jdi.connect.spi.TransportService;
import com.sun.jdi.event.VMDisconnectEvent;
import com.sun.jdi.event.VMStartEvent;
A manager of connections to target virtual machines. The VirtualMachineManager allows one application to debug multiple target VMs. (Note that the converse is not supported; a target VM can be debugged by only one debugger application.) This interface contains methods to manage connections to remote target VMs and to obtain the VirtualMachine
mirror for available target VMs. Connections can be made using one of several different Connector
objects. Each connector encapsulates a different way of connecting the debugger with a target VM.
The VirtualMachineManager supports many different scenarios for connecting a debugger to a virtual machine. Four examples are presented in the table below. The examples use the command line syntax in Sun's implementation. Some Connector
implementations may require slightly different handling than presented below.
Four scenarios for connecting a debugger to a virtual machine"
Scenario
Description
Debugger launches target VM (simplest, most-common scenario)
Debugger calls the LaunchingConnector.launch(Map<String,? extends Argument>)
method of the default connector, obtained with defaultConnector
. The target VM is launched, and a connection between that VM and the debugger is established. A VirtualMachine
mirror is returned. Or, for more control
- Debugger selects a connector from the list returned by
launchingConnectors
with desired characteristics (for example, transport type, etc.). - Debugger calls the
LaunchingConnector.launch(Map<String,? extends Argument>)
method of the selected connector. The target VM is launched, and a connection between that VM and the debugger is established. A VirtualMachine
mirror is returned.
Debugger attaches to previously-running VM
- Target VM is launched using the options
-agentlib:jdwp=transport=xxx,server=y
-
Target VM generates and outputs the tranport-specific address at which it will
listen for a connection.
- Debugger is launched. Debugger selects a connector in the list returned by
attachingConnectors
matching the transport with the name "xxx". - Debugger presents the default connector parameters (obtained through
Connector.defaultArguments()
) to the end user, allowing the user to fill in the transport-specific address generated by the target VM. - Debugger calls the
AttachingConnector.attach(Map<String,? extends Argument>)
method of the selected to attach to the target VM. A VirtualMachine
mirror is returned.
Target VM attaches to previously-running debugger
- At startup, debugger selects one or more connectors from the list returned by
listeningConnectors
for one or more transports.
- Debugger calls the
ListeningConnector.startListening(Map<String,? extends Argument>)
method for each selected connector. For each call, a transport-specific address string is generated and returned. The debugger makes the transport names and corresponding address strings available to the end user. - Debugger calls
ListeningConnector.accept(Map<String,? extends Argument>)
for each selected connector to wait for a target VM to connect.
- Later, target VM is launched by end user with the options
-agentlib:jdwp=transport=xxx,address=yyy
where "xxx" the transport for one of the connectors selected by the the debugger and "yyy" is the address generated by ListeningConnector.accept(Map<String,? extends Argument>)
for that transport.
- Debugger's call to
ListeningConnector.accept(Map<String,? extends Argument>)
returns a VirtualMachine
mirror.
Target VM launches debugger (sometimes called "Just-In-Time" debugging)
- Target VM is launched with the options
-agentlib:jdwp=launch=cmdline,onuncaught=y,transport=xxx,server=y
-
Later, an uncaught exception is thrown in the target VM. The target
VM generates the tranport-specific address at which it will
listen for a connection.
- Target VM launches the debugger with the following items concatenated
together (separated by spaces) to form the command line:
- The launch= value
- The transport= value
- The generated transport-specific address at which VM is listening for
debugger connection.
- Upon launch, debugger selects a connector in the list returned by
attachingConnectors
matching the transport with the name "xxx". - Debugger changes the default connector parameters (obtained through
Connector.defaultArguments()
) to specify the transport specific address at which the VM is listenig. Optionally, other connector arguments can be presented to the user. - Debugger calls the
AttachingConnector.attach(Map<String,? extends Argument>)
method of the selected to attach to the target VM. A VirtualMachine
mirror is returned.
Connectors are created at start-up time. That is, they are created the first time that Bootstrap.virtualMachineManager()
is invoked. The list of all Connectors created at start-up time can be obtained from the VirtualMachineManager by invoking the allConnectors
method.
Connectors are created at start-up time if they are installed on the platform. In addition, Connectors are created automatically by the VirtualMachineManager to encapsulate any TransportService
implementations that are installed on the platform. These two mechanisms for creating Connectors are described here.
A Connector is installed on the platform if it is installed in a jar file that is visible to the defining class loader of the Connector
type, and that jar file contains a provider configuration file named Connector
in the resource directory META-INF/services
, and the provider configuration file lists the full-qualified class name of the Connector implementation. A Connector is a class that implements the Connector
interface. More appropriately the class implements one of the specific Connector types, namely
AttachingConnector
,
ListeningConnector
, or
LaunchingConnector
. The format of the provider configuration file is one fully-qualified class name per line. Space and tab characters surrounding each class, as well as blank lines are ignored. The comment character is '#'
(0x23
), and on each line all characters following the first comment character are ignored. The file must be encoded in UTF-8.
At start-up time the VirtualMachineManager attempts to load
and instantiate (using the no-arg constructor) each class listed
in the provider configuration file. Exceptions thrown when loading
or creating the Connector are caught and ignored. In other words,
the start-up process continues despite of errors.
In addition to Connectors installed on the platform the VirtualMachineManager will also create Connectors to encapsulate any TransportService
implementations that are installed on the platform. A TransportService is installed on the platform if it installed in a jar file that is visible to the defining class loader for the TransportService
type, and that jar file contains a provider configuration file named TransportService
in the resource directory META-INF/services
, and the provider configuration file lists the full-qualified class name of the TransportService implementation. A TransportService is a concrete sub-class of
TransportService
. The format of the provider configuration file is the same as the provider configuration file for Connectors except that each class listed must be the fully-qualified class name of a class that implements the TransportService interface.
For each TransportService installed on the platform, the VirtualMachineManager creates a corresponding AttachingConnector
and ListeningConnector
. These Connectors are created to encapsulate a Transport
that in turn encapsulates the TransportService. The AttachingConnector will be named based on the name of the transport service concatenated with the string Attach
. For example, if the transport service name()
method returns telepathic
then the AttachingConnector will be named telepathicAttach
. Similiarly the ListeningConnector will be named with the string Listen
tagged onto the name of the transport service. The description()
method of both the AttachingConnector, and the ListeningConnector, will delegate to the
description()
method of the underlying transport service. Both the AttachingConnector and the ListeningConnector will have two Connector Arguments
. A StringArgument
named address
is the connector argument to specify the address to attach too, or to listen on. A IntegerArgument
named timeout
is the connector argument to specify the timeout when attaching, or accepting. The timeout connector may be ignored depending on if the transport service supports an attach timeout or accept timeout.
Initialization of the virtual machine manager will fail, that is Bootstrap.virtualMachineManager()
will throw an error if the virtual machine manager is unable to create any connectors.
Author: Gordon Hirsch Since: 1.3
/**
* A manager of connections to target virtual machines. The
* VirtualMachineManager allows one application to debug
* multiple target VMs. (Note that the converse is not
* supported; a target VM can be debugged by only one
* debugger application.) This interface
* contains methods to manage connections
* to remote target VMs and to obtain the {@link VirtualMachine}
* mirror for available target VMs.
* <p>
* Connections can be made using one of several different
* {@link Connector} objects. Each connector encapsulates
* a different way of connecting the debugger with a target VM.
* <p>
* The VirtualMachineManager supports many different scenarios for
* connecting a debugger to a virtual machine. Four examples
* are presented in the table below. The
* examples use the command line syntax in Sun's implementation.
* Some {@link Connector} implementations may require slightly
* different handling than presented below.
*
* <TABLE class="striped">
* <CAPTION style="display:none">Four scenarios for connecting a debugger to a virtual machine"</CAPTION>
* <THEAD>
* <TR>
* <TH scope="col">Scenario</TH>
* <TH scope="col">Description</TH>
* </THEAD>
* <TBODY>
* <TR>
* <TH scope="row">Debugger launches target VM (simplest, most-common scenario)</TH>
*
* <TD>Debugger calls the {@link LaunchingConnector#launch(java.util.Map)}
* method of the default connector, obtained with {@link #defaultConnector}. The
* target VM is launched, and a connection between that VM and the
* debugger is established. A {@link VirtualMachine} mirror is returned.
* <P>Or, for more control
* <UL>
* <LI>
* Debugger selects a connector from the list returned by
* {@link #launchingConnectors} with desired characteristics
* (for example, transport type, etc.).
* <LI>
* Debugger calls the {@link LaunchingConnector#launch(java.util.Map)}
* method of the selected connector. The
* target VM is launched, and a connection between that VM and the
* debugger is established. A {@link VirtualMachine} mirror is returned.
* </UL>
* </TD>
* </TR>
* <TR>
* <TH scope="row">Debugger attaches to previously-running VM</TH>
* <TD>
* <UL>
* <LI>
* Target VM is launched using the options
* {@code -agentlib:jdwp=transport=xxx,server=y}
* </LI>
* <LI>
* Target VM generates and outputs the tranport-specific address at which it will
* listen for a connection.</LI>
* <LI>
* Debugger is launched. Debugger selects a connector in the list
* returned by {@link #attachingConnectors} matching the transport with
* the name "xxx".
* <LI>
* Debugger presents the default connector parameters (obtained through
* {@link Connector#defaultArguments()}) to the end user, allowing the user to
* fill in the transport-specific address generated by the target VM.
* <LI>
* Debugger calls the {@link AttachingConnector#attach(java.util.Map)} method
* of the selected to attach to the target VM. A {@link VirtualMachine}
* mirror is returned.
* </UL>
* </TD>
* </TR>
*
* <TR>
* <TH scope="row">Target VM attaches to previously-running debugger</TH>
* <TD>
* <UL>
* <LI>
* At startup, debugger selects one or more connectors from
* the list returned by {@link #listeningConnectors} for one or more
* transports.</LI>
* <LI>
* Debugger calls the {@link ListeningConnector#startListening(java.util.Map)} method for each selected
* connector. For each call, a transport-specific address string is
* generated and returned. The debugger makes the transport names and
* corresponding address strings available to the end user.
* <LI>
* Debugger calls
* {@link ListeningConnector#accept(java.util.Map)}
* for each selected connector to wait for
* a target VM to connect.</LI>
* <LI>
* Later, target VM is launched by end user with the options
* {@code -agentlib:jdwp=transport=xxx,address=yyy}
* where "xxx" the transport for one of the connectors selected by the
* the debugger and "yyy"
* is the address generated by
* {@link ListeningConnector#accept(java.util.Map)} for that
* transport.</LI>
* <LI>
* Debugger's call to {@link ListeningConnector#accept(java.util.Map)} returns
* a {@link VirtualMachine} mirror.</LI>
* </UL>
* </TD>
* </TR>
*
* <TR>
* <TH scope="row">Target VM launches debugger (sometimes called "Just-In-Time" debugging)</TH>
* <TD>
* <UL>
* <LI>
* Target VM is launched with the options
* {@code -agentlib:jdwp=launch=cmdline,onuncaught=y,transport=xxx,server=y}
* </LI>
* <LI>
* Later, an uncaught exception is thrown in the target VM. The target
* VM generates the tranport-specific address at which it will
* listen for a connection.
* <LI>Target VM launches the debugger with the following items concatenated
* together (separated by spaces) to form the command line:
* <UL>
* <LI> The launch= value
* <LI> The transport= value
* <LI> The generated transport-specific address at which VM is listening for
* debugger connection.
* </UL>
* <LI>
* Upon launch, debugger selects a connector in the list
* returned by {@link #attachingConnectors} matching the transport with
* the name "xxx".
* <LI>
* Debugger changes the default connector parameters (obtained through
* {@link Connector#defaultArguments()}) to specify
* the transport specific address at which the VM is listenig. Optionally,
* other connector arguments can be presented to the user.
* <LI>
* Debugger calls the
* {@link AttachingConnector#attach(java.util.Map)} method
* of the selected to attach to the target VM. A {@link VirtualMachine}
* mirror is returned.
* </UL>
* </TD>
* </TR>
* </TBODY>
* </TABLE>
*
* <p> Connectors are created at start-up time. That is, they
* are created the first time that {@link
* Bootstrap#virtualMachineManager()} is invoked.
* The list of all Connectors created at start-up time can be
* obtained from the VirtualMachineManager by invoking the
* {@link #allConnectors allConnectors} method.
*
* <p> Connectors are created at start-up time if they are
* installed on the platform. In addition, Connectors are created
* automatically by the VirtualMachineManager to encapsulate any
* {@link TransportService} implementations
* that are installed on the platform. These two mechanisms for
* creating Connectors are described here.
*
* <p> A Connector is installed on the platform if it is installed
* in a jar file that is visible to the defining class loader of
* the {@link Connector} type,
* and that jar file contains a provider configuration file named
* {@code Connector} in the resource directory
* {@code META-INF/services}, and the provider configuration file
* lists the full-qualified class name of the Connector
* implementation. A Connector is a class that implements the
* {@link Connector Connector} interface. More
* appropriately the class implements one of the specific Connector
* types, namely {@link AttachingConnector
* AttachingConnector}, {@link ListeningConnector
* ListeningConnector}, or {@link LaunchingConnector
* LaunchingConnector}. The format of the provider configuration file
* is one fully-qualified class name per line. Space and tab characters
* surrounding each class, as well as blank lines are ignored. The
* comment character is {@code '#'} ({@code 0x23}), and on each
* line all characters following the first comment character are
* ignored. The file must be encoded in UTF-8.
*
* <p> At start-up time the VirtualMachineManager attempts to load
* and instantiate (using the no-arg constructor) each class listed
* in the provider configuration file. Exceptions thrown when loading
* or creating the Connector are caught and ignored. In other words,
* the start-up process continues despite of errors.
*
* <p> In addition to Connectors installed on the platform the
* VirtualMachineManager will also create Connectors to encapsulate
* any {@link TransportService} implementations
* that are installed on the platform. A TransportService is
* installed on the platform if it installed in a jar file that is
* visible to the defining class loader for the
* {@link TransportService} type, and that jar
* file contains a provider configuration file named
* {@code TransportService} in the resource
* directory {@code META-INF/services}, and the provider
* configuration file lists the full-qualified class name of the
* TransportService implementation. A TransportService is a concrete
* sub-class of {@link TransportService
* TransportService}. The format of the provider configuration file
* is the same as the provider configuration file for Connectors
* except that each class listed must be the fully-qualified class
* name of a class that implements the TransportService interface.
*
* <p> For each TransportService installed on the platform, the
* VirtualMachineManager creates a corresponding {@link AttachingConnector} and
* {@link ListeningConnector}. These Connectors are created to encapsulate a
* {@link Transport Transport} that in turn encapsulates the TransportService.
* The AttachingConnector will be named based on the name of the
* transport service concatenated with the string {@code Attach}.
* For example, if the transport service {@link
* TransportService#name() name()} method
* returns {@code telepathic} then the AttachingConnector will
* be named {@code telepathicAttach}. Similiarly the ListeningConnector
* will be named with the string {@code Listen} tagged onto the
* name of the transport service. The {@link
* Connector#description() description()} method
* of both the AttachingConnector, and the ListeningConnector, will
* delegate to the {@link TransportService#description()
* description()} method of the underlying transport service. Both
* the AttachingConnector and the ListeningConnector will have two
* Connector {@link com.sun.jdi.connect.Connector.Argument Arguments}.
* A {@link com.sun.jdi.connect.Connector.StringArgument StringArgument}
* named {@code address} is the connector argument to specify the
* address to attach too, or to listen on. A
* {@link com.sun.jdi.connect.Connector.IntegerArgument IntegerArgument}
* named {@code timeout} is the connector argument to specify the
* timeout when attaching, or accepting. The timeout connector may be
* ignored depending on if the transport service supports an attach
* timeout or accept timeout.
*
* <p> Initialization of the virtual machine manager will fail, that is
* {@link Bootstrap#virtualMachineManager()} will throw an
* error if the virtual machine manager is unable to create any
* connectors.
*
* @author Gordon Hirsch
* @since 1.3
*/
public interface VirtualMachineManager {
Identifies the default connector. This connector should
be used as the launching connector when selection of a
connector with specific characteristics is unnecessary.
Returns: the default LaunchingConnector
/**
* Identifies the default connector. This connector should
* be used as the launching connector when selection of a
* connector with specific characteristics is unnecessary.
*
* @return the default {@link LaunchingConnector}
*/
LaunchingConnector defaultConnector();
Returns the list of known LaunchingConnector
objects. Any of the returned objects can be used to launch a new target VM and immediately create a VirtualMachine
mirror for it. Note that a target VM launched by a launching connector is not guaranteed to be stable until after the VMStartEvent
has been received. Returns: a list of LaunchingConnector
objects.
/**
* Returns the list of known {@link LaunchingConnector} objects.
* Any of the returned objects can be used to launch a new target
* VM and immediately create a {@link VirtualMachine} mirror for it.
*
* Note that a target VM launched by a launching connector is not guaranteed
* to be stable until after the {@link VMStartEvent} has been received.
* @return a list of {@link LaunchingConnector} objects.
*/
List<LaunchingConnector> launchingConnectors();
Returns the list of known AttachingConnector
objects. Any of the returned objects can be used to attach to an existing target VM and create a VirtualMachine
mirror for it. Returns: a list of AttachingConnector
objects.
/**
* Returns the list of known {@link AttachingConnector} objects.
* Any of the returned objects can be used to attach to an existing target
* VM and create a {@link VirtualMachine} mirror for it.
*
* @return a list of {@link AttachingConnector} objects.
*/
List<AttachingConnector> attachingConnectors();
Returns the list of known ListeningConnector
objects. Any of the returned objects can be used to listen for a connection initiated by a target VM and create a VirtualMachine
mirror for it. Returns: a list of ListeningConnector
objects.
/**
* Returns the list of known {@link ListeningConnector} objects.
* Any of the returned objects can be used to listen for a
* connection initiated by a target VM
* and create a {@link VirtualMachine} mirror for it.
*
* @return a list of {@link ListeningConnector} objects.
*/
List<ListeningConnector> listeningConnectors();
Returns the list of all known Connector
objects. Returns: a list of Connector
objects.
/**
* Returns the list of all known {@link Connector} objects.
*
* @return a list of {@link Connector} objects.
*/
List<Connector> allConnectors();
Lists all target VMs which are connected to the debugger. The list includes VirtualMachine
instances for any target VMs which initiated a connection and any target VMs to which this manager has initiated a connection. A target VM will remain in this list until the VM is disconnected. VMDisconnectEvent
is placed in the event queue after the VM is removed from the list. Returns: a list of VirtualMachine
objects, each mirroring a target VM.
/**
* Lists all target VMs which are connected to the debugger.
* The list includes {@link VirtualMachine} instances for
* any target VMs which initiated a connection
* and any
* target VMs to which this manager has initiated a connection.
* A target VM will remain in this list
* until the VM is disconnected.
* {@link VMDisconnectEvent} is placed in the event queue
* after the VM is removed from the list.
*
* @return a list of {@link VirtualMachine} objects, each mirroring
* a target VM.
*/
List<VirtualMachine> connectedVirtualMachines();
Returns the major version number of the JDI interface. See VirtualMachine.version
target VM version and information and VirtualMachine.description
more version information. Returns: the integer major version number.
/**
* Returns the major version number of the JDI interface.
* See {@link VirtualMachine#version} target VM version and
* information and
* {@link VirtualMachine#description} more version information.
*
* @return the integer major version number.
*/
int majorInterfaceVersion();
Returns the minor version number of the JDI interface. See VirtualMachine.version
target VM version and information and VirtualMachine.description
more version information. Returns: the integer minor version number
/**
* Returns the minor version number of the JDI interface.
* See {@link VirtualMachine#version} target VM version and
* information and
* {@link VirtualMachine#description} more version information.
*
* @return the integer minor version number
*/
int minorInterfaceVersion();
Create a virtual machine mirror for a target VM.
Creates a virtual machine mirror for a target VM for which a Connection
already exists. A Connection is created when a Connector
establishes a connection and successfully handshakes with a target VM. A Connector can then use this method to create a virtual machine mirror to represent the composite state of the target VM.
The process
argument specifies the Process
object for the taget VM. It may be specified as null
. If the target VM is launched by a
LaunchingConnector
the process
argument should be specified, otherwise calling VirtualMachine.process()
on the created virtual machine will return null
.
This method exists so that Connectors may create
a virtual machine mirror when a connection is established
to a target VM. Only developers creating new Connector
implementations should need to make direct use of this
method.
Params: - connection –
The open connection to the target VM.
- process – If launched, the
Process
object for the target VM. null
if not launched.
Throws: - IOException –
if an I/O error occurs
- IllegalStateException –
if the connection is not open
See Also: Returns: new virtual machine representing the target VM. Since: 1.5
/**
* Create a virtual machine mirror for a target VM.
*
* <p> Creates a virtual machine mirror for a target VM
* for which a {@link Connection Connection}
* already exists. A Connection is created when a {@link
* Connector Connector} establishes
* a connection and successfully handshakes with a target VM.
* A Connector can then use this method to create a virtual machine
* mirror to represent the composite state of the target VM.
*
* <p> The {@code process} argument specifies the
* {@link java.lang.Process} object for the taget VM. It may be
* specified as {@code null}. If the target VM is launched
* by a {@link LaunchingConnector
* LaunchingConnector} the {@code process} argument should be
* specified, otherwise calling {@link VirtualMachine#process()}
* on the created virtual machine will return {@code null}.
*
* <p> This method exists so that Connectors may create
* a virtual machine mirror when a connection is established
* to a target VM. Only developers creating new Connector
* implementations should need to make direct use of this
* method.
*
* @param connection
* The open connection to the target VM.
*
* @param process
* If launched, the {@link java.lang.Process} object for
* the target VM. {@code null} if not launched.
*
* @return new virtual machine representing the target VM.
*
* @throws IOException
* if an I/O error occurs
*
* @throws IllegalStateException
* if the connection is not open
*
* @see Connection#isOpen()
* @see VirtualMachine#process()
*
* @since 1.5
*/
VirtualMachine createVirtualMachine(Connection connection, Process process) throws IOException;
Creates a new virtual machine.
This convenience method works as if by invoking createVirtualMachine(Connection, Process)
method and specifying null
as the process
argument.
This method exists so that Connectors may create
a virtual machine mirror when a connection is established
to a target VM. Only developers creating new Connector
implementations should need to make direct use of this
method.
Throws: - IOException –
if an I/O error occurs
- IllegalStateException –
if the connection is not open
Returns: the new virtual machine Since: 1.5
/**
* Creates a new virtual machine.
*
* <p> This convenience method works as if by invoking {@link
* #createVirtualMachine(Connection, Process)} method and
* specifying {@code null} as the {@code process} argument.
*
* <p> This method exists so that Connectors may create
* a virtual machine mirror when a connection is established
* to a target VM. Only developers creating new Connector
* implementations should need to make direct use of this
* method.
*
* @return the new virtual machine
*
* @throws IOException
* if an I/O error occurs
*
* @throws IllegalStateException
* if the connection is not open
*
* @since 1.5
*/
VirtualMachine createVirtualMachine(Connection connection) throws IOException;
}