View Javadoc

1   /***************************************************************************************
2    * Copyright (c) Jonas Bon?r, Alexandre Vasseur. All rights reserved.                 *
3    * http://aspectwerkz.codehaus.org                                                    *
4    * ---------------------------------------------------------------------------------- *
5    * The software in this package is published under the terms of the LGPL license      *
6    * a copy of which has been included with this distribution in the license.txt file.  *
7    **************************************************************************************/
8   package org.codehaus.aspectwerkz.hook;
9   
10  import com.sun.jdi.VirtualMachine;
11  import com.sun.jdi.Bootstrap;
12  import com.sun.jdi.connect.AttachingConnector;
13  import com.sun.jdi.connect.Connector;
14  import com.sun.jdi.connect.IllegalConnectorArgumentsException;
15  
16  import java.util.Map;
17  import java.util.Iterator;
18  import java.io.IOException;
19  
20  /***
21   * Isolation of JDWP dependancies to Plug online mode in a running / remote VM.
22   * See Plug.
23   *
24   * @author <a href="mailto:alex@gnilux.com">Alexandre Vasseur</a>
25   */
26  public class JDWPPlug {
27  
28      /***
29       * transport jdwp option
30       */
31      private final static String TRANSPORT_JDWP = "transport";
32  
33      /***
34       * address jdwp option
35       */
36      private final static String ADDRESS_JDWP = "address";
37  
38      /***
39       * Connects to a remote JVM using the jdwp options specified in jdwp
40       *
41       * @param jdwp
42       * @return VirtualMachine or null if failure
43       * @throws Exception
44       */
45      private VirtualMachine connect(Map jdwp) throws Exception {
46          String transport = (String) jdwp.get(TRANSPORT_JDWP);
47          String address = (String) jdwp.get(ADDRESS_JDWP);
48          String name = null;
49          if ("dt_socket".equals(transport)) {
50              name = "com.sun.jdi.SocketAttach";
51          } else if ("dt_shmem".equals(transport)) {
52              name = "com.sun.jdi.SharedMemoryAttach";
53          }
54          AttachingConnector connector = null;
55          for (Iterator i = Bootstrap.virtualMachineManager().attachingConnectors().iterator(); i.hasNext();) {
56              AttachingConnector aConnector = (AttachingConnector) i.next();
57              if (aConnector.name().equals(name)) {
58                  connector = aConnector;
59                  break;
60              }
61          }
62          if (connector == null) {
63              throw new Exception("no AttachingConnector for transport: " + transport);
64          }
65          Map args = connector.defaultArguments();
66          if ("dt_socket".equals(transport)) {
67              ((Connector.Argument) args.get("port")).setValue(address);
68          } else if ("dt_shmem".equals(transport)) {
69              ((Connector.Argument) args.get("name")).setValue(address);
70          }
71          try {
72              VirtualMachine vm = connector.attach(args);
73              return vm;
74          } catch (IllegalConnectorArgumentsException e) {
75              System.err.println("failed to attach to VM (" + transport + ", " + address + "):");
76              e.printStackTrace();
77              for (Iterator i = e.argumentNames().iterator(); i.hasNext();) {
78                  System.err.println("wrong or missing argument - " + i.next());
79              }
80              return null;
81          } catch (IOException e) {
82              System.err.println("failed to attach to VM (" + transport + ", " + address + "):");
83              e.printStackTrace();
84              return null;
85          }
86      }
87  
88      /***
89       * Resume the remote JVM, without hotswapping classes
90       *
91       * @param jdwp
92       * @throws Exception
93       */
94      public void resume(Map jdwp) throws Exception {
95          VirtualMachine vm = connect(jdwp);
96          if (vm != null) {
97              vm.resume();
98              vm.dispose();
99          }
100     }
101 
102     /***
103      * Prints information about the remote JVM and resume
104      *
105      * @param jdwp
106      * @throws Exception
107      */
108     public void info(Map jdwp) throws Exception {
109         VirtualMachine vm = connect(jdwp);
110         if (vm != null) {
111             System.out.println("java.vm.name = " + vm.name());
112             System.out.println("java.version = " + vm.version());
113             System.out.println(vm.description());
114             vm.resume();
115             vm.dispose();
116         }
117     }
118 
119     /***
120      * Hotswaps the java.lang.ClassLoader of the remote JVM and resume
121      *
122      * @param jdwp
123      * @throws Exception
124      */
125     public void hotswap(Map jdwp) throws Exception {
126         // @todo check it works at runtime not suspended
127         VirtualMachine vm = ClassLoaderPatcher.hotswapClassLoader(
128                 System.getProperty(
129                         ProcessStarter.CL_PRE_PROCESSOR_CLASSNAME_PROPERTY,
130                         org.codehaus.aspectwerkz.hook.impl.ClassLoaderPreProcessorImpl.class.getName()
131                 ), (String) jdwp
132                             .get(TRANSPORT_JDWP), (String) jdwp.get(ADDRESS_JDWP)
133         );
134         if (vm != null) {
135             vm.resume();
136             vm.dispose();
137         }
138     }
139 
140 
141 }