Save This Page
Home » openjdk-7 » sun » instrument » [javadoc | source]
    1   /*
    2    * Copyright 2003-2005 Sun Microsystems, Inc.  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.  Sun designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   22    * CA 95054 USA or visit www.sun.com if you need additional information or
   23    * have any questions.
   24    */
   25   
   26   package sun.instrument;
   27   
   28   
   29   import java.lang.instrument.Instrumentation;
   30   import java.lang.instrument.ClassFileTransformer;
   31   import java.security.ProtectionDomain;
   32   
   33   /*
   34    * Copyright 2003 Wily Technology, Inc.
   35    */
   36   
   37   /**
   38    * Support class for the InstrumentationImpl. Manages the list of registered transformers.
   39    * Keeps everything in the right order, deals with sync of the list,
   40    * and actually does the calling of the transformers.
   41    */
   42   public class TransformerManager
   43   {
   44       private class TransformerInfo {
   45           final ClassFileTransformer  mTransformer;
   46           String                      mPrefix;
   47   
   48           TransformerInfo(ClassFileTransformer transformer) {
   49               mTransformer = transformer;
   50               mPrefix = null;
   51           }
   52   
   53           ClassFileTransformer transformer() {
   54               return  mTransformer;
   55           }
   56   
   57           String getPrefix() {
   58               return mPrefix;
   59           }
   60   
   61           void setPrefix(String prefix) {
   62               mPrefix = prefix;
   63           }
   64       }
   65   
   66       /**
   67        * a given instance of this list is treated as immutable to simplify sync;
   68        * we pay copying overhead whenever the list is changed rather than every time
   69        * the list is referenced.
   70        * The array is kept in the order the transformers are added via addTransformer
   71        * (first added is 0, last added is length-1)
   72        * Use an array, not a List or other Collection. This keeps the set of classes
   73        * used by this code to a minimum. We want as few dependencies as possible in this
   74        * code, since it is used inside the class definition system. Any class referenced here
   75        * cannot be transformed by Java code.
   76        */
   77       private TransformerInfo[]  mTransformerList;
   78   
   79       /***
   80        * Is this TransformerManager for transformers capable of retransformation?
   81        */
   82       private boolean            mIsRetransformable;
   83   
   84       TransformerManager(boolean isRetransformable) {
   85           mTransformerList    = new TransformerInfo[0];
   86           mIsRetransformable  = isRetransformable;
   87       }
   88   
   89       boolean isRetransformable() {
   90           return mIsRetransformable;
   91       }
   92   
   93       public synchronized void
   94       addTransformer( ClassFileTransformer    transformer) {
   95           TransformerInfo[] oldList = mTransformerList;
   96           TransformerInfo[] newList = new TransformerInfo[oldList.length + 1];
   97           System.arraycopy(   oldList,
   98                               0,
   99                               newList,
  100                               0,
  101                               oldList.length);
  102           newList[oldList.length] = new TransformerInfo(transformer);
  103           mTransformerList = newList;
  104       }
  105   
  106       public synchronized boolean
  107       removeTransformer(ClassFileTransformer  transformer) {
  108           boolean                 found           = false;
  109           TransformerInfo[]       oldList         = mTransformerList;
  110           int                     oldLength       = oldList.length;
  111           int                     newLength       = oldLength - 1;
  112   
  113           // look for it in the list, starting at the last added, and remember
  114           // where it was if we found it
  115           int matchingIndex   = 0;
  116           for ( int x = oldLength - 1; x >= 0; x-- ) {
  117               if ( oldList[x].transformer() == transformer ) {
  118                   found           = true;
  119                   matchingIndex   = x;
  120                   break;
  121               }
  122           }
  123   
  124           // make a copy of the array without the matching element
  125           if ( found ) {
  126               TransformerInfo[]  newList = new TransformerInfo[newLength];
  127   
  128               // copy up to but not including the match
  129               if ( matchingIndex > 0 ) {
  130                   System.arraycopy(   oldList,
  131                                       0,
  132                                       newList,
  133                                       0,
  134                                       matchingIndex);
  135               }
  136   
  137               // if there is anything after the match, copy it as well
  138               if ( matchingIndex < (newLength) ) {
  139                   System.arraycopy(   oldList,
  140                                       matchingIndex + 1,
  141                                       newList,
  142                                       matchingIndex,
  143                                       (newLength) - matchingIndex);
  144               }
  145               mTransformerList = newList;
  146           }
  147           return found;
  148       }
  149   
  150       synchronized boolean
  151       includesTransformer(ClassFileTransformer transformer) {
  152           for (TransformerInfo info : mTransformerList) {
  153               if ( info.transformer() == transformer ) {
  154                   return true;
  155               }
  156           }
  157           return false;
  158       }
  159   
  160       // This function doesn't actually snapshot anything, but should be
  161       // used to set a local variable, which will snapshot the transformer
  162       // list because of the copying semantics of mTransformerList (see
  163       // the comment for mTransformerList).
  164       private TransformerInfo[]
  165       getSnapshotTransformerList() {
  166           return mTransformerList;
  167       }
  168   
  169       public byte[]
  170       transform(  ClassLoader         loader,
  171                   String              classname,
  172                   Class               classBeingRedefined,
  173                   ProtectionDomain    protectionDomain,
  174                   byte[]              classfileBuffer) {
  175           boolean someoneTouchedTheBytecode = false;
  176   
  177           TransformerInfo[]  transformerList = getSnapshotTransformerList();
  178   
  179           byte[]  bufferToUse = classfileBuffer;
  180   
  181           // order matters, gotta run 'em in the order they were added
  182           for ( int x = 0; x < transformerList.length; x++ ) {
  183               TransformerInfo         transformerInfo = transformerList[x];
  184               ClassFileTransformer    transformer = transformerInfo.transformer();
  185               byte[]                  transformedBytes = null;
  186   
  187               try {
  188                   transformedBytes = transformer.transform(   loader,
  189                                                               classname,
  190                                                               classBeingRedefined,
  191                                                               protectionDomain,
  192                                                               bufferToUse);
  193               }
  194               catch (Throwable t) {
  195                   // don't let any one transformer mess it up for the others.
  196                   // This is where we need to put some logging. What should go here? FIXME
  197               }
  198   
  199               if ( transformedBytes != null ) {
  200                   someoneTouchedTheBytecode = true;
  201                   bufferToUse = transformedBytes;
  202               }
  203           }
  204   
  205           // if someone modified it, return the modified buffer.
  206           // otherwise return null to mean "no transforms occurred"
  207           byte [] result;
  208           if ( someoneTouchedTheBytecode ) {
  209               result = bufferToUse;
  210           }
  211           else {
  212               result = null;
  213           }
  214   
  215           return result;
  216       }
  217   
  218   
  219       int
  220       getTransformerCount() {
  221           TransformerInfo[]  transformerList = getSnapshotTransformerList();
  222           return transformerList.length;
  223       }
  224   
  225       boolean
  226       setNativeMethodPrefix(ClassFileTransformer transformer, String prefix) {
  227           TransformerInfo[]  transformerList = getSnapshotTransformerList();
  228   
  229           for ( int x = 0; x < transformerList.length; x++ ) {
  230               TransformerInfo         transformerInfo = transformerList[x];
  231               ClassFileTransformer    aTransformer = transformerInfo.transformer();
  232   
  233               if ( aTransformer == transformer ) {
  234                   transformerInfo.setPrefix(prefix);
  235                   return true;
  236               }
  237           }
  238           return false;
  239       }
  240   
  241   
  242       String[]
  243       getNativeMethodPrefixes() {
  244           TransformerInfo[]  transformerList = getSnapshotTransformerList();
  245           String[] prefixes                  = new String[transformerList.length];
  246   
  247           for ( int x = 0; x < transformerList.length; x++ ) {
  248               TransformerInfo         transformerInfo = transformerList[x];
  249               prefixes[x] = transformerInfo.getPrefix();
  250           }
  251           return prefixes;
  252       }
  253   }

Save This Page
Home » openjdk-7 » sun » instrument » [javadoc | source]