changeset 5581:0243e41000c6 jdk7u10-b11

Merge
author lana
date Tue, 09 Oct 2012 13:56:45 -0700
parents feb861b1fba3 9741e9cbe91a
children d6991b06e0dd 41f46837b0b7
files
diffstat 11 files changed, 199 insertions(+), 147 deletions(-) [+]
line wrap: on
line diff
--- a/src/macosx/classes/sun/java2d/opengl/CGLGraphicsConfig.java	Wed Oct 03 17:42:08 2012 -0700
+++ b/src/macosx/classes/sun/java2d/opengl/CGLGraphicsConfig.java	Tue Oct 09 13:56:45 2012 -0700
@@ -84,11 +84,14 @@
     private OGLContext context;
     private Object disposerReferent = new Object();
 
+    private final int cachedMaxTextureSize;
+
     public static native int getDefaultPixFmt(int screennum);
     private static native boolean initCGL();
     private static native long getCGLConfigInfo(int screennum, int visualnum,
                                                 int swapInterval);
     private static native int getOGLCapabilities(long configInfo);
+    private static native int _getMaxTextureSize();
 
     static {
         cglAvailable = initCGL();
@@ -108,6 +111,10 @@
         // CGLGraphicsConfigInfo data when this object goes away
         Disposer.addRecord(disposerReferent,
                            new CGLGCDisposerRecord(pConfigInfo));
+
+        // 7200762: Workaround a deadlock by caching the value
+        //          A fix for JDK 8 will remove the workaround
+        this.cachedMaxTextureSize = _getMaxTextureSize();
     }
 
     @Override
@@ -500,9 +507,12 @@
         }
     }
 
+
     // 7160609: GL still fails to create a square texture of this size,
     //          so we use this value to cap the total display bounds.
-    native private static int getMaxTextureSize();
+    private int getMaxTextureSize() {
+        return cachedMaxTextureSize;
+    }
 
     @Override
     public int getMaxTextureWidth() {
--- a/src/macosx/native/sun/awt/AWTEvent.h	Wed Oct 03 17:42:08 2012 -0700
+++ b/src/macosx/native/sun/awt/AWTEvent.h	Tue Oct 09 13:56:45 2012 -0700
@@ -33,5 +33,7 @@
 void DeliverJavaMouseEvent(JNIEnv *env, NSEvent *event, jobject peer);
 void SendAdditionalJavaEvents(JNIEnv *env, NSEvent *nsEvent, jobject peer);
 jint GetJavaMouseModifiers(NSInteger button, NSUInteger modifierFlags);
+jint NsKeyModifiersToJavaModifiers(NSUInteger nsFlags, BOOL isExtMods);
+NSUInteger JavaModifiersToNsKeyModifiers(jint javaModifiers, BOOL isExtMods);
 
 #endif /* __AWTEVENT_H */
--- a/src/macosx/native/sun/awt/AWTEvent.m	Wed Oct 03 17:42:08 2012 -0700
+++ b/src/macosx/native/sun/awt/AWTEvent.m	Tue Oct 09 13:56:45 2012 -0700
@@ -244,6 +244,7 @@
     //NSUInteger cgsRightMask;
     unsigned short leftKeyCode;
     unsigned short rightKeyCode;
+    jint javaExtMask;
     jint javaMask;
     jint javaKey;
 }
@@ -254,6 +255,7 @@
         0,
         0,
         0, // no Java equivalent
+        0, // no Java equivalent
         java_awt_event_KeyEvent_VK_CAPS_LOCK
     },
     {
@@ -263,6 +265,7 @@
         56,
         60,
         java_awt_event_InputEvent_SHIFT_DOWN_MASK,
+        java_awt_event_InputEvent_SHIFT_MASK,
         java_awt_event_KeyEvent_VK_SHIFT
     },
     {
@@ -272,6 +275,7 @@
         59,
         62,
         java_awt_event_InputEvent_CTRL_DOWN_MASK,
+        java_awt_event_InputEvent_CTRL_MASK,
         java_awt_event_KeyEvent_VK_CONTROL
     },
     {
@@ -281,6 +285,7 @@
         58,
         61,
         java_awt_event_InputEvent_ALT_DOWN_MASK,
+        java_awt_event_InputEvent_ALT_MASK,
         java_awt_event_KeyEvent_VK_ALT
     },
     {
@@ -290,6 +295,7 @@
         55,
         54,
         java_awt_event_InputEvent_META_DOWN_MASK,
+        java_awt_event_InputEvent_META_MASK,
         java_awt_event_KeyEvent_VK_META
     },
     // NSNumericPadKeyMask
@@ -298,10 +304,11 @@
         0,
         0,
         0, // no Java equivalent
+        0, // no Java equivalent
         java_awt_event_KeyEvent_VK_HELP
     },
     // NSFunctionKeyMask
-    {0, 0, 0, 0, 0}
+    {0, 0, 0, 0, 0, 0}
 };
 
 /*
@@ -491,15 +498,14 @@
 /*
  * This returns the java modifiers for a key NSEvent.
  */
-static jint
-NsKeyModifiersToJavaModifiers(NSUInteger nsFlags)
+jint NsKeyModifiersToJavaModifiers(NSUInteger nsFlags, BOOL isExtMods)
 {
     jint javaModifiers = 0;
     const struct _nsKeyToJavaModifier* cur;
 
     for (cur = nsKeyToJavaModifierTable; cur->nsMask != 0; ++cur) {
         if ((cur->nsMask & nsFlags) != 0) {
-            javaModifiers |= cur->javaMask;
+            javaModifiers |= isExtMods? cur->javaExtMask : cur->javaMask;
         }
     }
 
@@ -507,6 +513,33 @@
 }
 
 /*
+ * This returns the NSEvent flags for java key modifiers.
+ */
+NSUInteger JavaModifiersToNsKeyModifiers(jint javaModifiers, BOOL isExtMods)
+{
+    NSUInteger nsFlags = 0;
+    const struct _nsKeyToJavaModifier* cur;
+
+    for (cur = nsKeyToJavaModifierTable; cur->nsMask != 0; ++cur) {
+        jint mask = isExtMods? cur->javaExtMask : cur->javaMask; 
+        if ((mask & javaModifiers) != 0) {
+            nsFlags |= cur->nsMask;
+        }
+    }
+
+    // special case
+    jint mask = isExtMods? java_awt_event_InputEvent_ALT_GRAPH_DOWN_MASK : 
+                           java_awt_event_InputEvent_ALT_GRAPH_MASK;
+
+    if ((mask & javaModifiers) != 0) {
+        nsFlags |= NSAlternateKeyMask;      
+    }
+
+    return nsFlags;
+}
+
+
+/*
  * Returns the correct java character for a key event.  Most unicode
  * characters don't require any fussing, but a few seem to need adjusting,
  * see nsCharToJavaChar.
@@ -517,7 +550,7 @@
     unichar returnValue = java_awt_event_KeyEvent_CHAR_UNDEFINED;
     NSString *chars = nil;
     unichar testChar = 0, testDeadChar = 0;
-    jint javaModifiers = NsKeyModifiersToJavaModifiers([event modifierFlags]);
+    jint javaModifiers = NsKeyModifiersToJavaModifiers([event modifierFlags], TRUE);
 
     switch ([event type]) {
     case NSFlagsChanged:
@@ -657,7 +690,7 @@
             testChar = [chars characterAtIndex:0];
         }
 
-        javaModifiers = NsKeyModifiersToJavaModifiers([event modifierFlags]);
+        javaModifiers = NsKeyModifiersToJavaModifiers([event modifierFlags], TRUE);
         if (javaModifiers == 0) {
       // TODO: dead key chars
 //            testDeadChar = GetDeadKeyCharacter(event);
@@ -692,7 +725,7 @@
 jint GetJavaMouseModifiers(NSInteger button, NSUInteger modifierFlags)
 {
     // Mousing needs the key modifiers
-    jint modifiers = NsKeyModifiersToJavaModifiers(modifierFlags);
+    jint modifiers = NsKeyModifiersToJavaModifiers(modifierFlags, TRUE);
 
 
     /*
@@ -788,7 +821,7 @@
     jint javaKeyCode, javaKeyLocation;
     BOOL postsTyped = NO;
     unichar testChar, testDeadChar = 0;
-    jint javaModifiers = NsKeyModifiersToJavaModifiers([nsEvent modifierFlags]);
+    jint javaModifiers = NsKeyModifiersToJavaModifiers([nsEvent modifierFlags], TRUE);
 
     if (javaModifiers == 0) {
         testDeadChar = [nsEvent deadKeyCharacter];
@@ -984,7 +1017,7 @@
 
 JNF_COCOA_ENTER(env);
 
-    jmodifiers = NsKeyModifiersToJavaModifiers(modifierFlags);
+    jmodifiers = NsKeyModifiersToJavaModifiers(modifierFlags, TRUE);
 
 JNF_COCOA_EXIT(env);
 
--- a/src/macosx/native/sun/awt/CDragSource.m	Wed Oct 03 17:42:08 2012 -0700
+++ b/src/macosx/native/sun/awt/CDragSource.m	Tue Oct 09 13:56:45 2012 -0700
@@ -460,7 +460,7 @@
     }
 
     // Convert fModifiers (extModifiers) to NS:
-    NSUInteger modifiers = [DnDUtilities mapJavaExtModifiersToNSKeyModifiers:fModifiers];
+    NSUInteger modifiers = JavaModifiersToNsKeyModifiers(fModifiers, TRUE); 
 
     // Just a dummy value ...
     NSInteger eventNumber = 0;
@@ -658,7 +658,7 @@
     }
 
     // b) drag actions (key modifiers) have changed:
-    jint modifiers = [DnDUtilities currentJavaExtKeyModifiers];
+    jint modifiers = NsKeyModifiersToJavaModifiers([NSEvent modifierFlags], YES);
     if (fDragKeyModifiers != modifiers) {
         NSDragOperation currentOp = [DnDUtilities nsDragOperationForModifiers:[NSEvent modifierFlags]];
         NSDragOperation allowedOp = [DnDUtilities mapJavaDragOperationToNS:fSourceActions] & currentOp;
--- a/src/macosx/native/sun/awt/CMenuItem.m	Wed Oct 03 17:42:08 2012 -0700
+++ b/src/macosx/native/sun/awt/CMenuItem.m	Tue Oct 09 13:56:45 2012 -0700
@@ -70,6 +70,18 @@
     JNIEnv *env = [ThreadUtilities getJNIEnv];
 JNF_COCOA_ENTER(env);
 
+    // If we are called as a result of user pressing a shorcut, do nothing,
+    // because AWTView has already sent corresponding key event to the Java 
+    // layer from performKeyEquivalent
+    NSEvent *currEvent = [[NSApplication sharedApplication] currentEvent];
+    if ([currEvent type] == NSKeyDown) {
+        NSString *menuKey = [sender keyEquivalent];
+        NSString *eventKey = [currEvent characters];
+        if ([menuKey isEqualToString:eventKey]) {
+            return;
+        }
+    }
+
     if (fIsCheckbox) {
         static JNF_CLASS_CACHE(jc_CCheckboxMenuItem, "sun/lwawt/macosx/CCheckboxMenuItem");
         static JNF_MEMBER_CACHE(jm_ckHandleAction, jc_CCheckboxMenuItem, "handleAction", "(Z)V");
@@ -83,14 +95,8 @@
         static JNF_CLASS_CACHE(jc_CMenuItem, "sun/lwawt/macosx/CMenuItem");
         static JNF_MEMBER_CACHE(jm_handleAction, jc_CMenuItem, "handleAction", "(JI)V"); // AWT_THREADING Safe (event)
 
-        NSEvent *currEvent = [[NSApplication sharedApplication] currentEvent];
         NSUInteger modifiers = [currEvent modifierFlags];
-        jint javaModifiers = 0;
-
-        if ((modifiers & NSCommandKeyMask) != 0)   javaModifiers |= java_awt_Event_META_MASK;
-        if ((modifiers & NSShiftKeyMask) != 0)     javaModifiers |= java_awt_Event_SHIFT_MASK;
-        if ((modifiers & NSControlKeyMask) != 0)   javaModifiers |= java_awt_Event_CTRL_MASK;
-        if ((modifiers & NSAlternateKeyMask) != 0) javaModifiers |= java_awt_Event_ALT_MASK;
+        jint javaModifiers = NsKeyModifiersToJavaModifiers(modifiers, NO);
 
         JNFCallVoidMethod(env, fPeer, jm_handleAction, UTC(currEvent), javaModifiers); // AWT_THREADING Safe (event)
     }
@@ -117,10 +123,7 @@
             modifiers &= ~java_awt_event_KeyEvent_SHIFT_MASK;
         }
 
-        if ((modifiers & java_awt_event_KeyEvent_SHIFT_MASK) != 0) modifierMask |= NSShiftKeyMask;
-        if ((modifiers & java_awt_event_KeyEvent_CTRL_MASK) != 0)  modifierMask |= NSControlKeyMask;
-        if ((modifiers & java_awt_event_KeyEvent_ALT_MASK) != 0)   modifierMask |= NSAlternateKeyMask;
-        if ((modifiers & java_awt_event_KeyEvent_META_MASK) != 0)  modifierMask |= NSCommandKeyMask;
+        modifierMask = JavaModifiersToNsKeyModifiers(modifiers, NO);
     }
 
     [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){
--- a/src/macosx/native/sun/awt/DnDUtilities.h	Wed Oct 03 17:42:08 2012 -0700
+++ b/src/macosx/native/sun/awt/DnDUtilities.h	Tue Oct 09 13:56:45 2012 -0700
@@ -42,7 +42,6 @@
 + (jint)narrowJavaDropActions:(jint)actions;
 
 // Mouse and key modifiers mapping:
-+ (NSUInteger)mapJavaExtModifiersToNSKeyModifiers:(jint)modifiers;
 + (NSUInteger)mapJavaExtModifiersToNSMouseDownButtons:(jint)modifiers;
 + (NSUInteger)mapJavaExtModifiersToNSMouseUpButtons:(jint)modifiers;
 
@@ -50,9 +49,6 @@
 + (jint)extractJavaExtKeyModifiersFromJavaExtModifiers:(jint)modifiers;
 + (jint)extractJavaExtMouseModifiersFromJavaExtModifiers:(jint)modifiers;
 
-// Get the current keyboard modifier keys as java modifiers (for operationChanged)
-+ (jint)currentJavaExtKeyModifiers;
-
 // Getting the state of the current Drag
 + (NSDragOperation)nsDragOperationForModifiers:(NSUInteger)modifiers;
 + (jint) javaKeyModifiersForNSDragOperation:(NSDragOperation)dragOp;
--- a/src/macosx/native/sun/awt/DnDUtilities.m	Wed Oct 03 17:42:08 2012 -0700
+++ b/src/macosx/native/sun/awt/DnDUtilities.m	Tue Oct 09 13:56:45 2012 -0700
@@ -161,28 +161,6 @@
 }
 
 // Mouse and key modifiers mapping:
-+ (NSUInteger)mapJavaExtModifiersToNSKeyModifiers:(jint)modifiers
-{
-    NSUInteger result = 0;
-
-    if ((modifiers & java_awt_event_InputEvent_SHIFT_DOWN_MASK) != 0)
-        result |= NSShiftKeyMask;
-
-    if ((modifiers & java_awt_event_InputEvent_CTRL_DOWN_MASK) != 0)
-        result |= NSControlKeyMask;
-
-    if ((modifiers & java_awt_event_InputEvent_META_DOWN_MASK) != 0)
-        result |= NSCommandKeyMask;
-
-    if ((modifiers & java_awt_event_InputEvent_ALT_DOWN_MASK) != 0)
-        result |= NSAlternateKeyMask;
-
-    if ((modifiers & java_awt_event_InputEvent_ALT_GRAPH_DOWN_MASK) != 0)
-        result |= NSAlternateKeyMask;
-
-    return result;
-}
-
 + (NSUInteger)mapJavaExtModifiersToNSMouseDownButtons:(jint)modifiers
 {
     NSUInteger result = NSLeftMouseDown;
@@ -245,32 +223,6 @@
     return modifiers & mask;
 }
 
-
-+ (jint)currentJavaExtKeyModifiers
-{
-    NSUInteger modifiers = [NSEvent modifierFlags];
-    jint jmodifiers = 0;
-
-    if(modifiers & NSShiftKeyMask) {
-        jmodifiers |= java_awt_event_InputEvent_SHIFT_DOWN_MASK;
-    }
-
-    if(modifiers & NSControlKeyMask) {
-        jmodifiers |= java_awt_event_InputEvent_CTRL_DOWN_MASK;
-    }
-
-    if(modifiers & NSAlternateKeyMask) {
-        jmodifiers |= java_awt_event_InputEvent_ALT_DOWN_MASK;
-    }
-
-    if(modifiers & NSCommandKeyMask) {
-        jmodifiers |= java_awt_event_InputEvent_META_DOWN_MASK;
-    }
-
-    return jmodifiers;
-}
-
-
 + (NSDragOperation) nsDragOperationForModifiers:(NSUInteger)modifiers {
 
     // Java first
--- a/src/macosx/native/sun/java2d/opengl/CGLGraphicsConfig.m	Wed Oct 03 17:42:08 2012 -0700
+++ b/src/macosx/native/sun/java2d/opengl/CGLGraphicsConfig.m	Tue Oct 09 13:56:45 2012 -0700
@@ -447,10 +447,10 @@
 }
 
 JNIEXPORT jint JNICALL
-Java_sun_java2d_opengl_CGLGraphicsConfig_getMaxTextureSize
+Java_sun_java2d_opengl_CGLGraphicsConfig__1getMaxTextureSize
     (JNIEnv *env, jclass cglgc)
 {
-    J2dTraceLn(J2D_TRACE_INFO, "CGLGraphicsConfig_getMaxTextureSize");
+    J2dTraceLn(J2D_TRACE_INFO, "CGLGraphicsConfig__1getMaxTextureSize");
 
     __block int max = 0;
 
--- a/src/share/classes/com/sun/crypto/provider/AESCrypt.java	Wed Oct 03 17:42:08 2012 -0700
+++ b/src/share/classes/com/sun/crypto/provider/AESCrypt.java	Tue Oct 09 13:56:45 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -37,6 +37,7 @@
 package com.sun.crypto.provider;
 
 import java.security.InvalidKeyException;
+import java.util.Arrays;
 
 /**
  * Rijndael --pronounced Reindaal-- is a symmetric cipher with a 128-bit
@@ -54,7 +55,12 @@
     private Object[] sessionK = null;
     private int[] K = null;
 
-    /** (ROUNDS-1) * 4 */
+    /** Cipher encryption/decryption key */
+    // skip re-generating Session and Sub keys if the cipher key is
+    // the same
+    private byte[] lastKey = null;
+
+    /** ROUNDS * 4 */
     private int limit = 0;
 
     AESCrypt() {
@@ -82,41 +88,45 @@
                 key.length + " bytes");
         }
 
-        // generate session key and reset sub key.
-        sessionK = makeKey(key);
-        setSubKey(decrypting);
+        if (!Arrays.equals(key, lastKey)) {
+            // re-generate session key 'sessionK' when cipher key changes
+            makeSessionKey(key);
+            lastKey = key.clone();  // save cipher key
+        }
+
+        // set sub key to the corresponding session Key
+        this.K = (int[]) sessionK[(decrypting? 1:0)];
     }
 
-    private void setSubKey(boolean decrypting) {
-        int[][] Kd = (int[][]) sessionK[decrypting ? 1 : 0];
-        int rounds = Kd.length;
-        this.K = new int[rounds*4];
-        for(int i=0; i<rounds; i++) {
+    /**
+     * Expand an int[(ROUNDS+1)][4] into int[(ROUNDS+1)*4].
+     * For decryption round keys, need to rotate right by 4 ints.
+     * @param kr The round keys for encryption or decryption.
+     * @param decrypting True if 'kr' is for decryption and false otherwise.
+     */
+    private static final int[] expandToSubKey(int[][] kr, boolean decrypting) {
+        int total = kr.length;
+        int[] expK = new int[total*4];
+        if (decrypting) {
+            // decrypting, rotate right by 4 ints
+            // i.e. i==0
             for(int j=0; j<4; j++) {
-                K[i*4 + j] = Kd[i][j];
+                expK[j] = kr[total-1][j];
+            }
+            for(int i=1; i<total; i++) {
+                for(int j=0; j<4; j++) {
+                    expK[i*4 + j] = kr[i-1][j];
+                }
+            }
+        } else {
+            // encrypting, straight expansion
+            for(int i=0; i<total; i++) {
+                for(int j=0; j<4; j++) {
+                    expK[i*4 + j] = kr[i][j];
+                }
             }
         }
-
-        if (decrypting) {
-            int j0 = K[K.length-4];
-            int j1 = K[K.length-3];
-            int j2 = K[K.length-2];
-            int j3 = K[K.length-1];
-
-            for (int i=this.K.length-1; i>3; i--) {
-                this.K[i] = this.K[i-4];
-            }
-            K[0] = j0;
-            K[1] = j1;
-            K[2] = j2;
-            K[3] = j3;
-        }
-
-        ROUNDS_12 = (rounds>=13);
-        ROUNDS_14 = (rounds==15);
-
-        rounds--;
-        limit=rounds*4;
+        return expK;
     }
 
     private static int[]
@@ -566,10 +576,10 @@
     /**
      * Expand a user-supplied key material into a session key.
      *
-     * @param key The 128/192/256-bit user-key to use.
+     * @param k The 128/192/256-bit cipher key to use.
      * @exception InvalidKeyException  If the key is invalid.
      */
-    private static Object[] makeKey(byte[] k) throws InvalidKeyException {
+    private void makeSessionKey(byte[] k) throws InvalidKeyException {
         if (k == null) {
             throw new InvalidKeyException("Empty key");
         }
@@ -639,10 +649,18 @@
                            U4[ tt         & 0xFF];
             }
         }
-        // assemble the encryption (Ke) and decryption (Kd) round keys into
-        // one sessionKey object
-        Object[] result = new Object[] {Ke, Kd};
-        return result;
+
+        // assemble the encryption (Ke) and decryption (Kd) round keys
+        // and expand them into arrays of ints.
+        int[] expandedKe = expandToSubKey(Ke, false); // decrypting==false
+        int[] expandedKd = expandToSubKey(Kd, true);  // decrypting==true
+
+        ROUNDS_12 = (ROUNDS>=12);
+        ROUNDS_14 = (ROUNDS==14);
+        limit = ROUNDS*4;
+
+        // store the expanded sub keys into 'sessionK'
+        sessionK = new Object[] { expandedKe, expandedKd };
     }
 
 
--- a/src/share/classes/javax/crypto/CryptoPermissions.java	Wed Oct 03 17:42:08 2012 -0700
+++ b/src/share/classes/javax/crypto/CryptoPermissions.java	Tue Oct 09 13:56:45 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -30,10 +30,16 @@
 import java.util.Hashtable;
 import java.util.Vector;
 import java.util.NoSuchElementException;
+import java.util.concurrent.ConcurrentHashMap;
 import java.io.Serializable;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.BufferedReader;
+import java.io.ObjectStreamField;
+import java.io.ObjectInputStream;
+import java.io.ObjectInputStream.GetField;
+import java.io.ObjectOutputStream;
+import java.io.ObjectOutputStream.PutField;
 import java.io.IOException;
 
 /**
@@ -61,15 +67,24 @@
 
     private static final long serialVersionUID = 4946547168093391015L;
 
-    // This class is similar to java.security.Permissions
-    private Hashtable perms;
+    /**
+     * @serialField perms java.util.Hashtable
+     */
+    private static final ObjectStreamField[] serialPersistentFields = {
+        new ObjectStreamField("perms", Hashtable.class),
+    };
+
+    // Switched from Hashtable to ConcurrentHashMap to improve scalability.
+    // To maintain serialization compatibility, this field is made transient
+    // and custom readObject/writeObject methods are used.
+    private transient ConcurrentHashMap<String,PermissionCollection> perms;
 
     /**
      * Creates a new CryptoPermissions object containing
      * no CryptoPermissionCollections.
      */
     CryptoPermissions() {
-        perms = new Hashtable(7);
+        perms = new ConcurrentHashMap<>(7);
     }
 
     /**
@@ -132,9 +147,7 @@
                         getPermissionCollection(cryptoPerm);
         pc.add(cryptoPerm);
         String alg = cryptoPerm.getAlgorithm();
-        if (!perms.containsKey(alg)) {
-            perms.put(alg, pc);
-        }
+        perms.putIfAbsent(alg, pc);
     }
 
     /**
@@ -382,20 +395,17 @@
     PermissionCollection getPermissionCollection(String alg) {
         // If this CryptoPermissions includes CryptoAllPermission,
         // we should return CryptoAllPermission.
-        if (perms.containsKey(CryptoAllPermission.ALG_NAME)) {
-            return
-                (PermissionCollection)(perms.get(CryptoAllPermission.ALG_NAME));
-        }
+        PermissionCollection pc = perms.get(CryptoAllPermission.ALG_NAME);
+        if (pc == null) {
+            pc = perms.get(alg);
 
-        PermissionCollection pc = (PermissionCollection)perms.get(alg);
-
-        // If there isn't a PermissionCollection for
-        // the given algorithm,we should return the
-        // PermissionCollection for the wildcard
-        // if there is one.
-        if (pc == null) {
-            pc = (PermissionCollection)perms.get(
-                                       CryptoPermission.ALG_NAME_WILDCARD);
+            // If there isn't a PermissionCollection for
+            // the given algorithm,we should return the
+            // PermissionCollection for the wildcard
+            // if there is one.
+            if (pc == null) {
+                pc = perms.get(CryptoPermission.ALG_NAME_WILDCARD);
+            }
         }
         return pc;
     }
@@ -421,6 +431,28 @@
         }
         return pc;
     }
+
+    private void readObject(ObjectInputStream s)
+        throws IOException, ClassNotFoundException {
+        ObjectInputStream.GetField fields = s.readFields();
+        @SuppressWarnings("unchecked")
+        Hashtable<String,PermissionCollection> permTable =
+                (Hashtable<String,PermissionCollection>)
+                (fields.get("perms", null));
+        if (permTable != null) {
+            perms = new ConcurrentHashMap<>(permTable);
+        } else {
+            perms = new ConcurrentHashMap<>();
+        }
+    }
+
+    private void writeObject(ObjectOutputStream s) throws IOException {
+        Hashtable<String,PermissionCollection> permTable =
+                new Hashtable<>(perms);
+        ObjectOutputStream.PutField fields = s.putFields();
+        fields.put("perms", permTable);
+        s.writeFields();
+    }
 }
 
 final class PermissionsEnumerator implements Enumeration {
@@ -463,7 +495,6 @@
         } else {
             throw new NoSuchElementException("PermissionsEnumerator");
         }
-
     }
 
     private Enumeration getNextEnumWithMore() {
--- a/src/share/classes/javax/crypto/JceSecurityManager.java	Wed Oct 03 17:42:08 2012 -0700
+++ b/src/share/classes/javax/crypto/JceSecurityManager.java	Tue Oct 09 13:56:45 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,6 +29,8 @@
 import java.net.*;
 import java.util.*;
 import java.util.jar.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 
 /**
  * The JCE security manager.
@@ -51,7 +53,10 @@
     private static final CryptoPermissions exemptPolicy;
     private static final CryptoAllPermission allPerm;
     private static final Vector TrustedCallersCache = new Vector(2);
-    private static final Map exemptCache = new HashMap();
+    private static final ConcurrentMap<URL,CryptoPermissions> exemptCache =
+            new ConcurrentHashMap<>();
+    private static final CryptoPermissions CACHE_NULL_MARK =
+            new CryptoPermissions();
 
     // singleton instance
     static final JceSecurityManager INSTANCE;
@@ -116,17 +121,19 @@
             return defaultPerm;
         }
 
-        CryptoPermissions appPerms;
-        synchronized (this.getClass()) {
-            if (exemptCache.containsKey(callerCodeBase)) {
-                appPerms = (CryptoPermissions)exemptCache.get(callerCodeBase);
-            } else {
-                appPerms = getAppPermissions(callerCodeBase);
-                exemptCache.put(callerCodeBase, appPerms);
+        CryptoPermissions appPerms = exemptCache.get(callerCodeBase);
+        if (appPerms == null) {
+            // no match found in cache
+            synchronized (this.getClass()) {
+                appPerms = exemptCache.get(callerCodeBase);
+                if (appPerms == null) {
+                    appPerms = getAppPermissions(callerCodeBase);
+                    exemptCache.putIfAbsent(callerCodeBase,
+                        (appPerms == null? CACHE_NULL_MARK:appPerms));
+                }
             }
         }
-
-        if (appPerms == null) {
+        if (appPerms == null || appPerms == CACHE_NULL_MARK) {
             return defaultPerm;
         }