1 /* 2 * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.tools.attach.spi; 27 28 import java.io.IOException; 29 import java.util.Collections; 30 import java.util.Iterator; 31 import java.util.ArrayList; 32 import java.util.List; 33 import com.sun.tools.attach.VirtualMachine; 34 import com.sun.tools.attach.VirtualMachineDescriptor; 35 import com.sun.tools.attach.AttachPermission; 36 import com.sun.tools.attach.AttachNotSupportedException; 37 import java.util.ServiceLoader; 38 39 /** 40 * Attach provider class for attaching to a Java virtual machine. 41 * 42 * <p> An attach provider is a concrete subclass of this class that has a 43 * zero-argument constructor and implements the abstract methods specified 44 * below. </p> 45 * 46 * <p> An attach provider implementation is typically tied to a Java virtual 47 * machine implementation, version, or even mode of operation. That is, a specific 48 * provider implementation will typically only be capable of attaching to 49 * a specific Java virtual machine implementation or version. For example, Sun's 50 * JDK implementation ships with provider implementations that can only attach to 51 * Sun's <i>HotSpot</i> virtual machine. In general, if an environment 52 * consists of Java virtual machines of different versions and from different 53 * vendors then there will be an attach provider implementation for each 54 * <i>family</i> of implementations or versions. </p> 55 * 56 * <p> An attach provider is identified by its {@link #name <i>name</i>} and 57 * {@link #type <i>type</i>}. The <i>name</i> is typically, but not required to 58 * be, a name that corresponds to the VM vendor. The Sun JDK implementation, 59 * for example, ships with attach providers that use the name <i>"sun"</i>. The 60 * <i>type</i> typically corresponds to the attach mechanism. For example, an 61 * implementation that uses the Doors inter-process communication mechanism 62 * might use the type <i>"doors"</i>. The purpose of the name and type is to 63 * identify providers in environments where there are multiple providers 64 * installed. </p> 65 * 66 * <p> AttachProvider implementations are loaded and instantiated at the first 67 * invocation of the {@link #providers() providers} method. This method 68 * attempts to load all provider implementations that are installed on the 69 * platform. </p> 70 * 71 * <p> All of the methods in this class are safe for use by multiple 72 * concurrent threads. </p> 73 * 74 * @since 1.6 75 */ 76 77 public abstract class AttachProvider { 78 79 private static final Object lock = new Object(); 80 private static List<AttachProvider> providers = null; 81 82 /** 83 * Initializes a new instance of this class. </p> 84 * 85 * @throws SecurityException 86 * If a security manager has been installed and it denies 87 * {@link com.sun.tools.attach.AttachPermission AttachPermission} 88 * <tt>("createAttachProvider")</tt> 89 */ 90 protected AttachProvider() { 91 SecurityManager sm = System.getSecurityManager(); 92 if (sm != null) 93 sm.checkPermission(new AttachPermission("createAttachProvider")); 94 } 95 96 /** 97 * Return this provider's name. </p> 98 * 99 * @return The name of this provider 100 */ 101 public abstract String name(); 102 103 /** 104 * Return this provider's type. </p> 105 * 106 * @return The type of this provider 107 */ 108 public abstract String type(); 109 110 /** 111 * Attaches to a Java virtual machine. 112 * 113 * <p> A Java virtual machine is identified by an abstract identifier. The 114 * nature of this identifier is platform dependent but in many cases it will be the 115 * string representation of the process identifier (or pid). </p> 116 * 117 * <p> This method parses the identifier and maps the identifier to a Java 118 * virtual machine (in an implementation dependent manner). If the identifier 119 * cannot be parsed by the provider then an {@link 120 * com.sun.tools.attach.AttachNotSupportedException AttachNotSupportedException} 121 * is thrown. Once parsed this method attempts to attach to the Java virtual machine. 122 * If the provider detects that the identifier corresponds to a Java virtual machine 123 * that does not exist, or it corresponds to a Java virtual machine that does not support 124 * the attach mechanism implemented by this provider, or it detects that the 125 * Java virtual machine is a version to which this provider cannot attach, then 126 * an <code>AttachNotSupportedException</code> is thrown. </p> 127 * 128 * @param id 129 * The abstract identifier that identifies the Java virtual machine. 130 * 131 * @return VirtualMachine representing the target virtual machine. 132 * 133 * @throws SecurityException 134 * If a security manager has been installed and it denies 135 * {@link com.sun.tools.attach.AttachPermission AttachPermission} 136 * <tt>("attachVirtualMachine")</tt>, or other permission 137 * required by the implementation. 138 * 139 * @throws AttachNotSupportedException 140 * If the identifier cannot be parsed, or it corresponds to 141 * to a Java virtual machine that does not exist, or it 142 * corresponds to a Java virtual machine which this 143 * provider cannot attach. 144 * 145 * @throws IOException 146 * If some other I/O error occurs 147 * 148 * @throws NullPointerException 149 * If <code>id</code> is <code>null</code> 150 */ 151 public abstract VirtualMachine attachVirtualMachine(String id) 152 throws AttachNotSupportedException, IOException; 153 154 /** 155 * Attaches to a Java virtual machine. 156 * 157 * <p> A Java virtual machine can be described using a {@link 158 * com.sun.tools.attach.VirtualMachineDescriptor VirtualMachineDescriptor}. 159 * This method invokes the descriptor's {@link 160 * com.sun.tools.attach.VirtualMachineDescriptor#provider() provider()} method 161 * to check that it is equal to this provider. It then attempts to attach to the 162 * Java virtual machine. 163 * 164 * @param vmd 165 * The virtual machine descriptor 166 * 167 * @return VirtualMachine representing the target virtual machine. 168 * 169 * @throws SecurityException 170 * If a security manager has been installed and it denies 171 * {@link com.sun.tools.attach.AttachPermission AttachPermission} 172 * <tt>("attachVirtualMachine")</tt>, or other permission 173 * required by the implementation. 174 * 175 * @throws AttachNotSupportedException 176 * If the descriptor's {@link 177 * com.sun.tools.attach.VirtualMachineDescriptor#provider() provider()} method 178 * returns a provider that is not this provider, or it does not correspond 179 * to a Java virtual machine to which this provider can attach. 180 * 181 * @throws IOException 182 * If some other I/O error occurs 183 * 184 * @throws NullPointerException 185 * If <code>vmd</code> is <code>null</code> 186 */ 187 public VirtualMachine attachVirtualMachine(VirtualMachineDescriptor vmd) 188 throws AttachNotSupportedException, IOException 189 { 190 if (vmd.provider() != this) { 191 throw new AttachNotSupportedException("provider mismatch"); 192 } 193 return attachVirtualMachine(vmd.id()); 194 } 195 196 /** 197 * Lists the Java virtual machines known to this provider. 198 * 199 * <p> This method returns a list of {@link 200 * com.sun.tools.attach.VirtualMachineDescriptor} elements. Each 201 * <code>VirtualMachineDescriptor</code> describes a Java virtual machine 202 * to which this provider can <i>potentially</i> attach. There isn't any 203 * guarantee that invoking {@link #attachVirtualMachine(VirtualMachineDescriptor) 204 * attachVirtualMachine} on each descriptor in the list will succeed. 205 * 206 * @return The list of virtual machine descriptors which describe the 207 * Java virtual machines known to this provider (may be empty). 208 */ 209 public abstract List<VirtualMachineDescriptor> listVirtualMachines(); 210 211 212 /** 213 * Returns a list of the installed attach providers. 214 * 215 * <p> An AttachProvider is installed on the platform if: 216 * 217 * <ul> 218 * <li><p>It is installed in a JAR file that is visible to the defining 219 * class loader of the AttachProvider type (usually, but not required 220 * to be, the {@link java.lang.ClassLoader#getSystemClassLoader system 221 * class loader}).</p></li> 222 * 223 * <li><p>The JAR file contains a provider configuration named 224 * <tt>com.sun.tools.attach.spi.AttachProvider</tt> in the resource directory 225 * <tt>META-INF/services</tt>. </p></li> 226 * 227 * <li><p>The provider configuration file lists the full-qualified class 228 * name of the AttachProvider implementation. </p></li> 229 * </ul> 230 * 231 * <p> The format of the provider configuration file is one fully-qualified 232 * class name per line. Space and tab characters surrounding each class name, 233 * as well as blank lines are ignored. The comment character is 234 * <tt>'#'</tt> (<tt>0x23</tt>), and on each line all characters following 235 * the first comment character are ignored. The file must be encoded in 236 * UTF-8. </p> 237 * 238 * <p> AttachProvider implementations are loaded and instantiated 239 * (using the zero-arg constructor) at the first invocation of this method. 240 * The list returned by the first invocation of this method is the list 241 * of providers. Subsequent invocations of this method return a list of the same 242 * providers. The list is unmodifable.</p> 243 * 244 * @return A list of the installed attach providers. 245 */ 246 public static List<AttachProvider> providers() { 247 synchronized (lock) { 248 if (providers == null) { 249 providers = new ArrayList<AttachProvider>(); 250 251 ServiceLoader<AttachProvider> providerLoader = 252 ServiceLoader.load(AttachProvider.class, 253 AttachProvider.class.getClassLoader()); 254 255 Iterator<AttachProvider> i = providerLoader.iterator(); 256 257 while (i.hasNext()) { 258 try { 259 providers.add(i.next()); 260 } catch (Throwable t) { 261 if (t instanceof ThreadDeath) { 262 ThreadDeath td = (ThreadDeath)t; 263 throw td; 264 } 265 // Ignore errors and exceptions 266 System.err.println(t); 267 } 268 } 269 } 270 return Collections.unmodifiableList(providers); 271 } 272 } 273 }