1 /* 2 * Copyright (c) 2005, 2013, 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. 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. 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. 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. 70 * 71 * <p> All of the methods in this class are safe for use by multiple 72 * concurrent threads. 73 * 74 * @since 1.6 75 */ 76 77 @jdk.Exported 78 public abstract class AttachProvider { 79 80 private static final Object lock = new Object(); 81 private static List<AttachProvider> providers = null; 82 83 /** 84 * Initializes a new instance of this class. 85 * 86 * @throws SecurityException 87 * If a security manager has been installed and it denies 88 * {@link com.sun.tools.attach.AttachPermission AttachPermission} 89 * ("{@code createAttachProvider}") 90 */ 91 protected AttachProvider() { 92 SecurityManager sm = System.getSecurityManager(); 93 if (sm != null) 94 sm.checkPermission(new AttachPermission("createAttachProvider")); 95 } 96 97 /** 98 * Return this provider's name. 99 * 100 * @return The name of this provider 101 */ 102 public abstract String name(); 103 104 /** 105 * Return this provider's type. 106 * 107 * @return The type of this provider 108 */ 109 public abstract String type(); 110 111 /** 112 * Attaches to a Java virtual machine. 113 * 114 * <p> A Java virtual machine is identified by an abstract identifier. The 115 * nature of this identifier is platform dependent but in many cases it will be the 116 * string representation of the process identifier (or pid). 117 * 118 * <p> This method parses the identifier and maps the identifier to a Java 119 * virtual machine (in an implementation dependent manner). If the identifier 120 * cannot be parsed by the provider then an 121 * {@link com.sun.tools.attach.AttachNotSupportedException AttachNotSupportedException} 122 * is thrown. Once parsed this method attempts to attach to the Java virtual machine. 123 * If the provider detects that the identifier corresponds to a Java virtual machine 124 * that does not exist, or it corresponds to a Java virtual machine that does not support 125 * the attach mechanism implemented by this provider, or it detects that the 126 * Java virtual machine is a version to which this provider cannot attach, then 127 * an {@code AttachNotSupportedException} is thrown. 128 * 129 * @param id 130 * The abstract identifier that identifies the Java virtual machine. 131 * 132 * @return VirtualMachine representing the target virtual machine. 133 * 134 * @throws SecurityException 135 * If a security manager has been installed and it denies 136 * {@link com.sun.tools.attach.AttachPermission AttachPermission} 137 * ("{@code attachVirtualMachine}"), or other permission 138 * required by the implementation. 139 * 140 * @throws AttachNotSupportedException 141 * If the identifier cannot be parsed, or it corresponds to 142 * to a Java virtual machine that does not exist, or it 143 * corresponds to a Java virtual machine which this 144 * provider cannot attach. 145 * 146 * @throws IOException 147 * If some other I/O error occurs 148 * 149 * @throws NullPointerException 150 * If {@code id} is {@code null} 151 */ 152 public abstract VirtualMachine attachVirtualMachine(String id) 153 throws AttachNotSupportedException, IOException; 154 155 /** 156 * Attaches to a Java virtual machine. 157 * 158 * <p> A Java virtual machine can be described using a 159 * {@link com.sun.tools.attach.VirtualMachineDescriptor VirtualMachineDescriptor}. 160 * This method invokes the descriptor's 161 * {@link com.sun.tools.attach.VirtualMachineDescriptor#provider() provider()} method 162 * to check that it is equal to this provider. It then attempts to attach to the 163 * Java virtual machine. 164 * 165 * @param vmd 166 * The virtual machine descriptor 167 * 168 * @return VirtualMachine representing the target virtual machine. 169 * 170 * @throws SecurityException 171 * If a security manager has been installed and it denies 172 * {@link com.sun.tools.attach.AttachPermission AttachPermission} 173 * ("{@code attachVirtualMachine}"), or other permission 174 * required by the implementation. 175 * 176 * @throws AttachNotSupportedException 177 * If the descriptor's 178 * {@link com.sun.tools.attach.VirtualMachineDescriptor#provider() provider()} 179 * method returns a provider that is not this provider, or it does not 180 * correspond to a Java virtual machine to which this provider can attach. 181 * 182 * @throws IOException 183 * If some other I/O error occurs 184 * 185 * @throws NullPointerException 186 * If {@code vmd} is {@code null} 187 */ 188 public VirtualMachine attachVirtualMachine(VirtualMachineDescriptor vmd) 189 throws AttachNotSupportedException, IOException 190 { 191 if (vmd.provider() != this) { 192 throw new AttachNotSupportedException("provider mismatch"); 193 } 194 return attachVirtualMachine(vmd.id()); 195 } 196 197 /** 198 * Lists the Java virtual machines known to this provider. 199 * 200 * <p> This method returns a list of 201 * {@link com.sun.tools.attach.VirtualMachineDescriptor} elements. Each 202 * {@code VirtualMachineDescriptor} describes a Java virtual machine 203 * to which this provider can <i>potentially</i> attach. There isn't any 204 * guarantee that invoking 205 * {@link #attachVirtualMachine(VirtualMachineDescriptor) attachVirtualMachine} 206 * on each descriptor in the list will succeed. 207 * 208 * @return The list of virtual machine descriptors which describe the 209 * Java virtual machines known to this provider (may be empty). 210 */ 211 public abstract List<VirtualMachineDescriptor> listVirtualMachines(); 212 213 214 /** 215 * Returns a list of the installed attach providers. 216 * 217 * <p> An AttachProvider is installed on the platform if: 218 * 219 * <ul> 220 * <li>It is installed in a JAR file that is visible to the defining 221 * class loader of the AttachProvider type (usually, but not required 222 * to be, the {@link java.lang.ClassLoader#getSystemClassLoader system 223 * class loader}).</li> 224 * 225 * <li>The JAR file contains a provider configuration named 226 * {@code com.sun.tools.attach.spi.AttachProvider} in the resource directory 227 * {@code META-INF/services}.</li> 228 * 229 * <li>The provider configuration file lists the full-qualified class 230 * name of the AttachProvider implementation.</li> 231 * </ul> 232 * 233 * <p> The format of the provider configuration file is one fully-qualified 234 * class name per line. Space and tab characters surrounding each class name, 235 * as well as blank lines are ignored. The comment character is 236 * {@code '#'} ({@code 0x23}), and on each line all characters following 237 * the first comment character are ignored. The file must be encoded in 238 * UTF-8. 239 * 240 * <p> AttachProvider implementations are loaded and instantiated 241 * (using the zero-arg constructor) at the first invocation of this method. 242 * The list returned by the first invocation of this method is the list 243 * of providers. Subsequent invocations of this method return a list of the same 244 * providers. The list is unmodifable. 245 * 246 * @return A list of the installed attach providers. 247 */ 248 public static List<AttachProvider> providers() { 249 synchronized (lock) { 250 if (providers == null) { 251 providers = new ArrayList<AttachProvider>(); 252 253 ServiceLoader<AttachProvider> providerLoader = 254 ServiceLoader.load(AttachProvider.class, 255 AttachProvider.class.getClassLoader()); 256 257 Iterator<AttachProvider> i = providerLoader.iterator(); 258 259 while (i.hasNext()) { 260 try { 261 providers.add(i.next()); 262 } catch (Throwable t) { 263 if (t instanceof ThreadDeath) { 264 ThreadDeath td = (ThreadDeath)t; 265 throw td; 266 } 267 // Ignore errors and exceptions 268 System.err.println(t); 269 } 270 } 271 } 272 return Collections.unmodifiableList(providers); 273 } 274 } 275 }