< prev index next >

src/java.base/share/classes/java/lang/ClassValue.java

Print this page
@  rev 60626 : 8251397: NPE on ClassValue.ClassValueMap.cacheArray
|  Reviewed-by: aph
~


  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 java.lang;
  27 
  28 import java.util.WeakHashMap;
  29 import java.lang.ref.WeakReference;
  30 import java.util.concurrent.atomic.AtomicInteger;
  31 


  32 import static java.lang.ClassValue.ClassValueMap.probeHomeLocation;
  33 import static java.lang.ClassValue.ClassValueMap.probeBackupLocations;
  34 
  35 /**
  36  * Lazily associate a computed value with (potentially) every type.
  37  * For example, if a dynamic language needs to construct a message dispatch
  38  * table for each class encountered at a message send call site,
  39  * it can use a {@code ClassValue} to cache information needed to
  40  * perform the message send quickly, for each class encountered.
  41  * @author John Rose, JSR 292 EG
  42  * @since 1.7
  43  */
  44 public abstract class ClassValue<T> {
  45     /**
  46      * Sole constructor.  (For invocation by subclass constructors, typically
  47      * implicit.)
  48      */
  49     protected ClassValue() {
  50     }
  51 


 394         // or if the version goes immediately dead and is nulled out,
 395         // the reader will take the slow path and retry under a lock.
 396     }
 397 
 398     // The following class could also be top level and non-public:
 399 
 400     /** A backing map for all ClassValues.
 401      *  Gives a fully serialized "true state" for each pair (ClassValue cv, Class type).
 402      *  Also manages an unserialized fast-path cache.
 403      */
 404     static class ClassValueMap extends WeakHashMap<ClassValue.Identity, Entry<?>> {
 405         private Entry<?>[] cacheArray;
 406         private int cacheLoad, cacheLoadLimit;
 407 
 408         /** Number of entries initially allocated to each type when first used with any ClassValue.
 409          *  It would be pointless to make this much smaller than the Class and ClassValueMap objects themselves.
 410          *  Must be a power of 2.
 411          */
 412         private static final int INITIAL_ENTRIES = 32;
 413 


 414         /** Build a backing map for ClassValues.
 415          *  Also, create an empty cache array and install it on the class.
 416          */
 417         ClassValueMap() {
 418             sizeCache(INITIAL_ENTRIES);


 419         }
 420 
 421         Entry<?>[] getCache() { return cacheArray; }
 422 
 423         /** Initiate a query.  Store a promise (placeholder) if there is no value yet. */
 424         synchronized
 425         <T> Entry<T> startEntry(ClassValue<T> classValue) {
 426             @SuppressWarnings("unchecked")  // one map has entries for all value types <T>
 427             Entry<T> e = (Entry<T>) get(classValue.identity);
 428             Version<T> v = classValue.version();
 429             if (e == null) {
 430                 e = v.promise();
 431                 // The presence of a promise means that a value is pending for v.
 432                 // Eventually, finishEntry will overwrite the promise.
 433                 put(classValue.identity, e);
 434                 // Note that the promise is never entered into the cache!
 435                 return e;
 436             } else if (e.isPromise()) {
 437                 // Somebody else has asked the same question.
 438                 // Let the races begin!




  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 java.lang;
  27 
  28 import java.util.WeakHashMap;
  29 import java.lang.ref.WeakReference;
  30 import java.util.concurrent.atomic.AtomicInteger;
  31 
  32 import jdk.internal.misc.Unsafe;
  33 
  34 import static java.lang.ClassValue.ClassValueMap.probeHomeLocation;
  35 import static java.lang.ClassValue.ClassValueMap.probeBackupLocations;
  36 
  37 /**
  38  * Lazily associate a computed value with (potentially) every type.
  39  * For example, if a dynamic language needs to construct a message dispatch
  40  * table for each class encountered at a message send call site,
  41  * it can use a {@code ClassValue} to cache information needed to
  42  * perform the message send quickly, for each class encountered.
  43  * @author John Rose, JSR 292 EG
  44  * @since 1.7
  45  */
  46 public abstract class ClassValue<T> {
  47     /**
  48      * Sole constructor.  (For invocation by subclass constructors, typically
  49      * implicit.)
  50      */
  51     protected ClassValue() {
  52     }
  53 


 396         // or if the version goes immediately dead and is nulled out,
 397         // the reader will take the slow path and retry under a lock.
 398     }
 399 
 400     // The following class could also be top level and non-public:
 401 
 402     /** A backing map for all ClassValues.
 403      *  Gives a fully serialized "true state" for each pair (ClassValue cv, Class type).
 404      *  Also manages an unserialized fast-path cache.
 405      */
 406     static class ClassValueMap extends WeakHashMap<ClassValue.Identity, Entry<?>> {
 407         private Entry<?>[] cacheArray;
 408         private int cacheLoad, cacheLoadLimit;
 409 
 410         /** Number of entries initially allocated to each type when first used with any ClassValue.
 411          *  It would be pointless to make this much smaller than the Class and ClassValueMap objects themselves.
 412          *  Must be a power of 2.
 413          */
 414         private static final int INITIAL_ENTRIES = 32;
 415 
 416         private static final Unsafe UNSAFE = Unsafe.getUnsafe();
 417 
 418         /** Build a backing map for ClassValues.
 419          *  Also, create an empty cache array and install it on the class.
 420          */
 421         ClassValueMap() {
 422             sizeCache(INITIAL_ENTRIES);
 423             // Trailing release fence to get safe publication
 424             UNSAFE.storeFence();
 425         }
 426 
 427         Entry<?>[] getCache() { return cacheArray; }
 428 
 429         /** Initiate a query.  Store a promise (placeholder) if there is no value yet. */
 430         synchronized
 431         <T> Entry<T> startEntry(ClassValue<T> classValue) {
 432             @SuppressWarnings("unchecked")  // one map has entries for all value types <T>
 433             Entry<T> e = (Entry<T>) get(classValue.identity);
 434             Version<T> v = classValue.version();
 435             if (e == null) {
 436                 e = v.promise();
 437                 // The presence of a promise means that a value is pending for v.
 438                 // Eventually, finishEntry will overwrite the promise.
 439                 put(classValue.identity, e);
 440                 // Note that the promise is never entered into the cache!
 441                 return e;
 442             } else if (e.isPromise()) {
 443                 // Somebody else has asked the same question.
 444                 // Let the races begin!


< prev index next >