Save This Page
Home » openjdk-7 » com.sun.corba.se.impl » util » [javadoc | source]
    1   /*
    2    * Copyright (c) 1999, 2004, 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    * Licensed Materials - Property of IBM
   27    * RMI-IIOP v1.0
   28    * Copyright IBM Corp. 1998 1999  All Rights Reserved
   29    *
   30    */
   31   
   32   package com.sun.corba.se.impl.util;
   33   
   34   import sun.corba.Bridge;
   35   
   36   import java.util.Map;
   37   import java.util.WeakHashMap;
   38   import java.util.Collections;
   39   
   40   import java.security.AccessController;
   41   import java.security.PrivilegedAction;
   42   
   43   /**
   44    *  Utility method for crawling call stack to load class
   45    */
   46   class JDKClassLoader {
   47   
   48       private static final JDKClassLoaderCache classCache
   49           = new JDKClassLoaderCache();
   50   
   51       private static final Bridge bridge =
   52           (Bridge)AccessController.doPrivileged(
   53               new PrivilegedAction() {
   54                   public Object run() {
   55                       return Bridge.get() ;
   56                   }
   57               }
   58           ) ;
   59   
   60       static Class loadClass(Class aClass, String className)
   61           throws ClassNotFoundException {
   62   
   63           // Maintain the same error semantics as Class.forName()
   64           if (className == null) {
   65               throw new NullPointerException();
   66           }
   67           if (className.length() == 0) {
   68               throw new ClassNotFoundException();
   69           }
   70   
   71           // It would be nice to bypass JDKClassLoader's attempts completely
   72           // if it's known that the latest user defined ClassLoader will
   73           // fail.
   74           //
   75           // Otherwise, we end up calling Class.forName here as well as in
   76           // the next step in JDKBridge.  That can take a long time depending
   77           // on the length of the classpath.
   78   
   79           // Note: Looking at the only place in JDKBridge where this code
   80           // is invoked, it is clear that aClass will always be null.
   81           ClassLoader loader;
   82           if (aClass != null) {
   83               loader = aClass.getClassLoader();
   84           } else {
   85               loader = bridge.getLatestUserDefinedLoader();
   86           }
   87           // See createKey for a description of what's involved
   88           Object key = classCache.createKey(className, loader);
   89   
   90           if (classCache.knownToFail(key)) {
   91               throw new ClassNotFoundException(className);
   92           } else {
   93               try {
   94                   // Loading this class with the call stack
   95                   // loader isn't known to fail, so try
   96                   // to load it.
   97                   return Class.forName(className, false, loader);
   98               } catch(ClassNotFoundException cnfe) {
   99                   // Record that we failed to find the class
  100                   // with this particular loader.  This way, we won't
  101                   // waste time looking with this loader, again.
  102                   classCache.recordFailure(key);
  103                   throw cnfe;
  104               }
  105           }
  106       }
  107   
  108       /**
  109        * Private cache implementation specific to JDKClassLoader.
  110        */
  111       private static class JDKClassLoaderCache
  112       {
  113           // JDKClassLoader couldn't find the class with the located
  114           // ClassLoader.  Note this in our cache so JDKClassLoader
  115           // can abort early next time.
  116           public final void recordFailure(Object key) {
  117               cache.put(key, JDKClassLoaderCache.KNOWN_TO_FAIL);
  118           }
  119   
  120           // Factory for a key (CacheKey is an implementation detail
  121           // of JDKClassLoaderCache).
  122           //
  123           // A key currently consists of the class name as well as
  124           // the latest user defined class loader, so it's fairly
  125           // expensive to create.
  126           public final Object createKey(String className, ClassLoader latestLoader) {
  127               return new CacheKey(className, latestLoader);
  128           }
  129   
  130           // Determine whether or not this combination of class name
  131           // and ClassLoader is known to fail.
  132           public final boolean knownToFail(Object key) {
  133               return cache.get(key) == JDKClassLoaderCache.KNOWN_TO_FAIL;
  134           }
  135   
  136           // Synchronized WeakHashMap
  137           private final Map cache
  138               = Collections.synchronizedMap(new WeakHashMap());
  139   
  140           // Cache result used to mark the caches when there is
  141           // no way JDKClassLoader could succeed with the given
  142           // key
  143           private static final Object KNOWN_TO_FAIL = new Object();
  144   
  145           // Key consisting of the class name and the latest
  146           // user defined class loader
  147           private static class CacheKey
  148           {
  149               String className;
  150               ClassLoader loader;
  151   
  152               public CacheKey(String className, ClassLoader loader) {
  153                   this.className = className;
  154                   this.loader = loader;
  155               }
  156   
  157               // Try to incorporate both class name and loader
  158               // into the hashcode
  159               public int hashCode() {
  160                   if (loader == null)
  161                       return className.hashCode();
  162                   else
  163                       return className.hashCode() ^ loader.hashCode();
  164               }
  165   
  166               public boolean equals(Object obj) {
  167                   try {
  168   
  169                       // WeakHashMap may compare null keys
  170                       if (obj == null)
  171                           return false;
  172   
  173                       CacheKey other = (CacheKey)obj;
  174   
  175                       // I've made a decision to actually compare the
  176                       // loader references.  I don't want a case when
  177                       // two loader instances override their equals
  178                       // methods and only compare code base.
  179                       //
  180                       // This way, at worst, our performance will
  181                       // be slower, but we know we'll do the correct
  182                       // loading.
  183                       return (className.equals(other.className) &&
  184                               loader == other.loader);
  185   
  186                   } catch (ClassCastException cce) {
  187                       return false;
  188                   }
  189               }
  190           }
  191       }
  192   }

Save This Page
Home » openjdk-7 » com.sun.corba.se.impl » util » [javadoc | source]