Source for gnu.java.lang.InstrumentationImpl

   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: }