Frames | No Frames |
1: /* InstrumentationImpl.java -- GNU implementation of 2: java.lang.instrument.Instrumentation 3: Copyright (C) 2005, 2006 Free Software Foundation, Inc. 4: 5: This file is part of GNU Classpath. 6: 7: GNU Classpath is free software; you can redistribute it and/or modify 8: it under the terms of the GNU General Public License as published by 9: the Free Software Foundation; either version 2, or (at your option) 10: any later version. 11: 12: GNU Classpath is distributed in the hope that it will be useful, but 13: WITHOUT ANY WARRANTY; without even the implied warranty of 14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15: General Public License for more details. 16: 17: You should have received a copy of the GNU General Public License 18: along with GNU Classpath; see the file COPYING. If not, write to the 19: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20: 02110-1301 USA. 21: 22: Linking this library statically or dynamically with other modules is 23: making a combined work based on this library. Thus, the terms and 24: conditions of the GNU General Public License cover the whole 25: combination. 26: 27: As a special exception, the copyright holders of this library give you 28: permission to link this library with independent modules to produce an 29: executable, regardless of the license terms of these independent 30: modules, and to copy and distribute the resulting executable under 31: terms of your choice, provided that you also meet, for each linked 32: independent module, the terms and conditions of the license of that 33: module. An independent module is a module which is not derived from 34: or based on this library. If you modify this library, you may extend 35: this exception to your version of the library, but you are not 36: obligated to do so. If you do not wish to do so, delete this 37: exception statement from your version. */ 38: 39: 40: package gnu.java.lang; 41: 42: import java.lang.instrument.Instrumentation; 43: import java.lang.instrument.ClassFileTransformer; 44: import java.lang.instrument.ClassDefinition; 45: import java.lang.instrument.UnmodifiableClassException; 46: import java.lang.instrument.IllegalClassFormatException; 47: 48: import java.security.ProtectionDomain; 49: 50: import java.util.ArrayList; 51: import java.util.Iterator; 52: 53: /** 54: * An Instrumentation object has transformers that will 55: * be called each time a class is defined or redefined. 56: * The object is given to a <code>premain</code> function 57: * that is called before the <code>main</code> function. 58: * 59: * @author Nicolas Geoffray (nicolas.geoffray@menlina.com) 60: * @since 1.5 61: */ 62: public final class InstrumentationImpl implements Instrumentation 63: { 64: 65: /* List of transformers */ 66: private ArrayList<ClassFileTransformer> transformers = 67: new ArrayList<ClassFileTransformer>(); 68: 69: 70: InstrumentationImpl() 71: { 72: } 73: 74: /** 75: * Adds a <code>ClassFileTransformer</class> object 76: * to the instrumentation. Each time a class is defined 77: * or redefined, the <code>transform</code> method of the 78: * <code>transformer</code> object is called. 79: * 80: * @param transformer the transformer to add 81: * @throws NullPointerException if transformer is null 82: */ 83: public void addTransformer(ClassFileTransformer transformer) 84: { 85: if (transformer == null) 86: throw new NullPointerException(); 87: synchronized(transformers) 88: { 89: transformers.add(transformer); 90: } 91: } 92: 93: /** 94: * Removes the given transformer from the set of transformers 95: * this Instrumentation object has. 96: * 97: * @param transformer the transformer to remove 98: * @return true if the transformer was found and removed, false if 99: * the transformer was not found 100: * @throws NullPointerException if transformer is null 101: */ 102: public boolean removeTransformer(ClassFileTransformer transformer) 103: { 104: if (transformer == null) 105: throw new NullPointerException(); 106: 107: boolean result; 108: synchronized (transformers) 109: { 110: result = transformers.remove(transformer); 111: } 112: return result; 113: } 114: 115: /** 116: * Returns if the current JVM supports class redefinition 117: * 118: * @return true if the current JVM supports class redefinition 119: */ 120: public boolean isRedefineClassesSupported() 121: { 122: return VMInstrumentationImpl.isRedefineClassesSupported(); 123: } 124: 125: /** 126: * Redefine classes present in the definitions array, with 127: * the corresponding class files. 128: * 129: * @param definitions an array of classes to redefine 130: * 131: * @throws ClassNotFoundException if a class cannot be found 132: * @throws UnmodifiableClassException if a class cannot be modified 133: * @throws UnsupportedOperationException if the JVM does not support 134: * redefinition or the redefinition made unsupported changes 135: * @throws ClassFormatError if a class file is not valid 136: * @throws NoClassDefFoundError if a class name is not equal to the name 137: * in the class file specified 138: * @throws UnsupportedClassVersionError if the class file version numbers 139: * are unsupported 140: * @throws ClassCircularityError if circularity occured with the new 141: * classes 142: * @throws LinkageError if a linkage error occurs 143: * @throws NullPointerException if the definitions array is null, or any 144: * of its element 145: * 146: * @see isRedefineClassesSupported() 147: * @see addTransformer(java.lang.instrument.ClassFileTransformer) 148: * @see ClassFileTransformer 149: */ 150: public void redefineClasses(ClassDefinition[] definitions) 151: throws ClassNotFoundException, 152: UnmodifiableClassException 153: { 154: if (!isRedefineClassesSupported()) 155: throw new UnsupportedOperationException(); 156: 157: VMInstrumentationImpl.redefineClasses(this, definitions); 158: } 159: 160: 161: /** 162: * Get all the classes loaded by the JVM. 163: * 164: * @return an array containing all the classes loaded by the JVM. The array 165: * is empty if no class is loaded. 166: */ 167: public Class[] getAllLoadedClasses() 168: { 169: return VMInstrumentationImpl.getAllLoadedClasses(); 170: } 171: 172: /** 173: * Get all the classes loaded by a given class loader 174: * 175: * @param loader the loader 176: * 177: * @return an array containing all the classes loaded by the given loader. 178: * The array is empty if no class was loaded by the loader. 179: */ 180: public Class[] getInitiatedClasses(ClassLoader loader) 181: { 182: return VMInstrumentationImpl.getInitiatedClasses(loader); 183: } 184: 185: /** 186: * Get the size of an object. 187: * 188: * @param objectToSize the object 189: * @return the size of the object 190: * @throws NullPointerException if objectToSize is null. 191: */ 192: public long getObjectSize(Object objectToSize) 193: { 194: // We alleviate the VM work 195: if (objectToSize == null) 196: throw new NullPointerException(); 197: return VMInstrumentationImpl.getObjectSize(objectToSize); 198: } 199: 200: /** 201: * Called by the VM or redefineClasses to call each transformer 202: * 203: * @param loader the loader of the class 204: * @param className the name of the class with packages separated with "/" 205: * @param classBeingRedefined the class being redefined if it's the case, 206: * null otherwise 207: * @param protectionDomain the protection domain of the class being defined 208: * or redefined 209: * @param classfileBuffer the input byte buffer in class file format 210: * 211: * @return the new class file 212: */ 213: public byte[] callTransformers(ClassLoader loader, String className, 214: Class<?> classBeingRedefined, ProtectionDomain protectionDomain, 215: byte[] classfileBuffer) 216: { 217: byte[] newBuffer = null; 218: byte[] oldBuffer = classfileBuffer; 219: ClassFileTransformer current; 220: synchronized (transformers) 221: { 222: Iterator<ClassFileTransformer> i = transformers.iterator(); 223: while (i.hasNext()) 224: { 225: current = i.next(); 226: try 227: { 228: newBuffer = current.transform(loader, className, 229: classBeingRedefined, protectionDomain, oldBuffer); 230: } 231: catch (IllegalClassFormatException ignored) 232: { 233: //IGNORED 234: } 235: if (newBuffer != null) 236: oldBuffer = newBuffer; 237: } 238: } 239: return oldBuffer; 240: } 241: }