diff -Nru openjdk.orig/corba/src/share/classes/com/sun/corba/se/impl/encoding/CachedCodeBase.java openjdk/corba/src/share/classes/com/sun/corba/se/impl/encoding/CachedCodeBase.java
--- openjdk.orig/corba/src/share/classes/com/sun/corba/se/impl/encoding/CachedCodeBase.java	2012-10-26 19:21:48.000000000 +0100
+++ openjdk/corba/src/share/classes/com/sun/corba/se/impl/encoding/CachedCodeBase.java	2013-02-13 16:50:31.269776235 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -22,7 +22,6 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-
 package com.sun.corba.se.impl.encoding;
 
 import java.util.Hashtable;
@@ -32,7 +31,8 @@
 import com.sun.org.omg.SendingContext._CodeBaseImplBase;
 import com.sun.org.omg.SendingContext._CodeBaseStub;
 import com.sun.corba.se.spi.transport.CorbaConnection;
-
+import com.sun.corba.se.spi.ior.IOR;
+import com.sun.corba.se.spi.orb.ORB;
 /**
  * Provides the reading side with a per connection cache of
  * info obtained via calls to the remote CodeBase.
@@ -51,14 +51,24 @@
  *
  * Needs cache management.
  */
-// REVISIT: revert to package protected after framework merge.
 public class CachedCodeBase extends _CodeBaseImplBase
 {
     private Hashtable implementations, fvds, bases;
-    private CodeBase delegate;
+    private volatile CodeBase delegate;
     private CorbaConnection conn;
 
-    private static Hashtable iorToCodeBaseObjMap = new Hashtable();
+    private static Object iorMapLock = new Object();
+    private static Hashtable<IOR,CodeBase> iorMap = new Hashtable<IOR,CodeBase>();
+
+    public static synchronized void cleanCache( ORB orb ) {
+        synchronized (iorMapLock) {
+            for (IOR ior : iorMap.keySet()) {
+                if (ior.getORB() == orb) {
+                    iorMap.remove(ior);
+                }
+            }
+        }
+    }
 
     public CachedCodeBase(CorbaConnection connection) {
         conn = connection;
@@ -68,7 +78,7 @@
         return null;
     }
 
-    public String implementation (String repId) {
+    public synchronized String implementation (String repId) {
         String urlResult = null;
 
         if (implementations == null)
@@ -86,7 +96,7 @@
         return urlResult;
     }
 
-    public String[] implementations (String[] repIds) {
+    public synchronized String[] implementations (String[] repIds) {
         String[] urlResults = new String[repIds.length];
 
         for (int i = 0; i < urlResults.length; i++)
@@ -95,7 +105,7 @@
         return urlResults;
     }
 
-    public FullValueDescription meta (String repId) {
+    public synchronized FullValueDescription meta (String repId) {
         FullValueDescription result = null;
 
         if (fvds == null)
@@ -113,7 +123,7 @@
         return result;
     }
 
-    public FullValueDescription[] metas (String[] repIds) {
+    public synchronized FullValueDescription[] metas (String[] repIds) {
         FullValueDescription[] results
             = new FullValueDescription[repIds.length];
 
@@ -123,7 +133,7 @@
         return results;
     }
 
-    public String[] bases (String repId) {
+    public synchronized String[] bases (String repId) {
 
         String[] results = null;
 
@@ -145,7 +155,7 @@
     // Ensures that we've used the connection's IOR to create
     // a valid CodeBase delegate.  If this returns false, then
     // it is not valid to access the delegate.
-    private boolean connectedCodeBase() {
+    private synchronized boolean connectedCodeBase() {
         if (delegate != null)
             return true;
 
@@ -165,7 +175,7 @@
             return false;
         }
 
-        synchronized(this) {
+        synchronized(iorMapLock) {
 
             // Recheck the condition to make sure another
             // thread didn't already do this while we waited
@@ -173,7 +183,8 @@
                 return true;
 
             // Do we have a reference initialized by another connection?
-            delegate = (CodeBase)CachedCodeBase.iorToCodeBaseObjMap.get(conn.getCodeBaseIOR());
+            delegate = CachedCodeBase.iorMap.get(conn.getCodeBaseIOR());
+
             if (delegate != null)
                 return true;
 
@@ -181,8 +192,7 @@
             delegate = CodeBaseHelper.narrow(getObjectFromIOR());
 
             // Save it for the benefit of other connections
-            CachedCodeBase.iorToCodeBaseObjMap.put(conn.getCodeBaseIOR(),
-                                                   delegate);
+            CachedCodeBase.iorMap.put(conn.getCodeBaseIOR(), delegate);
         }
 
         // It's now safe to use the delegate
diff -Nru openjdk.orig/corba/src/share/classes/com/sun/corba/se/impl/interceptors/PIHandlerImpl.java openjdk/corba/src/share/classes/com/sun/corba/se/impl/interceptors/PIHandlerImpl.java
--- openjdk.orig/corba/src/share/classes/com/sun/corba/se/impl/interceptors/PIHandlerImpl.java	2013-02-13 16:50:15.177517576 +0000
+++ openjdk/corba/src/share/classes/com/sun/corba/se/impl/interceptors/PIHandlerImpl.java	2013-02-13 16:50:31.277776364 +0000
@@ -58,7 +58,7 @@
 import org.omg.PortableInterceptor.TRANSPORT_RETRY;
 import org.omg.PortableInterceptor.USER_EXCEPTION;
 import org.omg.PortableInterceptor.PolicyFactory;
-import org.omg.PortableInterceptor.ObjectReferenceTemplate ;
+import org.omg.PortableInterceptor.ObjectReferenceTemplate;
 
 import com.sun.corba.se.pept.encoding.OutputObject;
 
@@ -112,10 +112,10 @@
         }
     }
 
-    private ORB orb ;
-    InterceptorsSystemException wrapper ;
-    ORBUtilSystemException orbutilWrapper ;
-    OMGSystemException omgWrapper ;
+    private ORB orb;
+    InterceptorsSystemException wrapper;
+    ORBUtilSystemException orbutilWrapper;
+    OMGSystemException omgWrapper;
 
     // A unique id used in ServerRequestInfo.
     // This does not correspond to the GIOP request id.
@@ -178,6 +178,21 @@
             }
         };
 
+    public void close() {
+        orb = null;
+        wrapper = null;
+        orbutilWrapper = null;
+        omgWrapper = null;
+        codecFactory = null;
+        arguments = null;
+        interceptorList = null;
+        interceptorInvoker = null;
+        current = null;
+        policyFactoryTable = null;
+        threadLocalClientRequestInfoStack = null;
+        threadLocalServerRequestInfoStack = null;
+    }
+
     // Class to contain all ThreadLocal data for ClientRequestInfo
     // maintenance.
     //
diff -Nru openjdk.orig/corba/src/share/classes/com/sun/corba/se/impl/interceptors/PINoOpHandlerImpl.java openjdk/corba/src/share/classes/com/sun/corba/se/impl/interceptors/PINoOpHandlerImpl.java
--- openjdk.orig/corba/src/share/classes/com/sun/corba/se/impl/interceptors/PINoOpHandlerImpl.java	2013-02-13 16:50:15.177517576 +0000
+++ openjdk/corba/src/share/classes/com/sun/corba/se/impl/interceptors/PINoOpHandlerImpl.java	2013-02-13 16:50:31.277776364 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -69,6 +69,9 @@
     public PINoOpHandlerImpl( ) {
     }
 
+    public void close() {
+    }
+
     public void initialize() {
     }
 
diff -Nru openjdk.orig/corba/src/share/classes/com/sun/corba/se/impl/monitoring/MonitoringManagerFactoryImpl.java openjdk/corba/src/share/classes/com/sun/corba/se/impl/monitoring/MonitoringManagerFactoryImpl.java
--- openjdk.orig/corba/src/share/classes/com/sun/corba/se/impl/monitoring/MonitoringManagerFactoryImpl.java	2012-10-26 19:21:48.000000000 +0100
+++ openjdk/corba/src/share/classes/com/sun/corba/se/impl/monitoring/MonitoringManagerFactoryImpl.java	2013-02-13 16:50:31.277776364 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -34,14 +34,18 @@
     private HashMap monitoringManagerTable = new HashMap();
 
     public synchronized MonitoringManager createMonitoringManager(
-        String nameOfTheRoot, String description )
+        String nameOfTheRoot, String description)
     {
         MonitoringManagerImpl m = null;
         m = (MonitoringManagerImpl)monitoringManagerTable.get(nameOfTheRoot);
         if (m == null) {
-            m = new MonitoringManagerImpl( nameOfTheRoot, description );
+            m = new MonitoringManagerImpl(nameOfTheRoot, description);
             monitoringManagerTable.put(nameOfTheRoot, m);
         }
         return m;
     }
+
+    public synchronized void remove(String nameOfTheRoot) {
+        monitoringManagerTable.remove(nameOfTheRoot);
+    }
 }
diff -Nru openjdk.orig/corba/src/share/classes/com/sun/corba/se/impl/monitoring/MonitoringManagerImpl.java openjdk/corba/src/share/classes/com/sun/corba/se/impl/monitoring/MonitoringManagerImpl.java
--- openjdk.orig/corba/src/share/classes/com/sun/corba/se/impl/monitoring/MonitoringManagerImpl.java	2012-10-26 19:21:48.000000000 +0100
+++ openjdk/corba/src/share/classes/com/sun/corba/se/impl/monitoring/MonitoringManagerImpl.java	2013-02-13 16:50:31.281776428 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -26,6 +26,7 @@
 package com.sun.corba.se.impl.monitoring;
 
 import com.sun.corba.se.spi.monitoring.MonitoringManager;
+import com.sun.corba.se.spi.monitoring.MonitoringManagerFactory;
 import com.sun.corba.se.spi.monitoring.MonitoredObject;
 import com.sun.corba.se.spi.monitoring.MonitoredObjectFactory;
 import com.sun.corba.se.spi.monitoring.MonitoringFactories;
@@ -33,18 +34,24 @@
 public class MonitoringManagerImpl implements MonitoringManager {
     private final MonitoredObject rootMonitoredObject;
 
-    MonitoringManagerImpl( String nameOfTheRoot, String description ) {
+    MonitoringManagerImpl(String nameOfTheRoot, String description) {
         MonitoredObjectFactory f =
             MonitoringFactories.getMonitoredObjectFactory();
         rootMonitoredObject =
-            f.createMonitoredObject( nameOfTheRoot, description );
+            f.createMonitoredObject(nameOfTheRoot, description);
     }
 
-    public void clearState( ) {
-        rootMonitoredObject.clearState( );
+    public void clearState() {
+        rootMonitoredObject.clearState();
     }
 
-    public MonitoredObject getRootMonitoredObject( ) {
+    public MonitoredObject getRootMonitoredObject() {
         return rootMonitoredObject;
     }
+
+    public void close() {
+        MonitoringManagerFactory f =
+            MonitoringFactories.getMonitoringManagerFactory();
+        f.remove(rootMonitoredObject.getName());
+    }
 }
diff -Nru openjdk.orig/corba/src/share/classes/com/sun/corba/se/impl/orb/ORBImpl.java openjdk/corba/src/share/classes/com/sun/corba/se/impl/orb/ORBImpl.java
--- openjdk.orig/corba/src/share/classes/com/sun/corba/se/impl/orb/ORBImpl.java	2013-02-13 16:50:15.185517704 +0000
+++ openjdk/corba/src/share/classes/com/sun/corba/se/impl/orb/ORBImpl.java	2013-02-13 16:50:31.281776428 +0000
@@ -23,35 +23,37 @@
  * questions.
  */
 
-package com.sun.corba.se.impl.orb ;
+package com.sun.corba.se.impl.orb;
 
 import java.applet.Applet;
 
-import java.io.IOException ;
+import java.io.IOException;
 
 import java.lang.reflect.Constructor;
-import java.lang.reflect.Field ;
-import java.lang.reflect.Modifier ;
-import java.lang.reflect.InvocationTargetException ;
-
-import java.util.ArrayList ;
-import java.util.Iterator ;
-import java.util.Properties ;
-import java.util.Vector ;
-import java.util.Hashtable ;
-import java.util.Map ;
-import java.util.HashMap ;
-import java.util.LinkedList ;
-import java.util.Collection ;
-import java.util.Collections ;
-import java.util.StringTokenizer ;
-import java.util.Enumeration ;
-import java.util.WeakHashMap ;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.InvocationTargetException;
+
+import java.util.Set;
+import java.util.HashSet;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.Properties;
+import java.util.Vector;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.StringTokenizer;
+import java.util.Enumeration;
+import java.util.WeakHashMap;
 
-import java.net.InetAddress ;
+import java.net.InetAddress;
 
 import java.security.PrivilegedAction;
-import java.security.AccessController ;
+import java.security.AccessController;
 
 import javax.rmi.CORBA.Util;
 import javax.rmi.CORBA.ValueHandler;
@@ -82,18 +84,18 @@
 import com.sun.org.omg.SendingContext.CodeBase;
 
 import com.sun.corba.se.pept.broker.Broker;
-import com.sun.corba.se.pept.protocol.ClientInvocationInfo ;
+import com.sun.corba.se.pept.protocol.ClientInvocationInfo;
 import com.sun.corba.se.pept.transport.ContactInfo;
 import com.sun.corba.se.pept.transport.ConnectionCache;
 import com.sun.corba.se.pept.transport.TransportManager;
 
 import com.sun.corba.se.spi.ior.IOR;
-import com.sun.corba.se.spi.ior.IdentifiableFactoryFinder ;
+import com.sun.corba.se.spi.ior.IdentifiableFactoryFinder;
 import com.sun.corba.se.spi.ior.TaggedComponentFactoryFinder;
-import com.sun.corba.se.spi.ior.IORFactories ;
-import com.sun.corba.se.spi.ior.ObjectKey ;
-import com.sun.corba.se.spi.ior.ObjectKeyFactory ;
-import com.sun.corba.se.spi.ior.iiop.IIOPFactories ;
+import com.sun.corba.se.spi.ior.IORFactories;
+import com.sun.corba.se.spi.ior.ObjectKey;
+import com.sun.corba.se.spi.ior.ObjectKeyFactory;
+import com.sun.corba.se.spi.ior.iiop.IIOPFactories;
 import com.sun.corba.se.spi.ior.iiop.GIOPVersion;
 import com.sun.corba.se.spi.oa.OAInvocationInfo;
 import com.sun.corba.se.spi.oa.ObjectAdapterFactory;
@@ -122,10 +124,10 @@
 import com.sun.corba.se.spi.transport.CorbaContactInfoListFactory;
 import com.sun.corba.se.spi.transport.CorbaTransportManager;
 import com.sun.corba.se.spi.legacy.connection.LegacyServerSocketManager;
-import com.sun.corba.se.spi.copyobject.CopierManager ;
-import com.sun.corba.se.spi.presentation.rmi.PresentationDefaults ;
-import com.sun.corba.se.spi.presentation.rmi.PresentationManager ;
-import com.sun.corba.se.spi.presentation.rmi.StubAdapter ;
+import com.sun.corba.se.spi.copyobject.CopierManager;
+import com.sun.corba.se.spi.presentation.rmi.PresentationDefaults;
+import com.sun.corba.se.spi.presentation.rmi.PresentationManager;
+import com.sun.corba.se.spi.presentation.rmi.StubAdapter;
 import com.sun.corba.se.spi.servicecontext.ServiceContextRegistry;
 
 import com.sun.corba.se.impl.corba.TypeCodeFactory;
@@ -140,6 +142,7 @@
 import com.sun.corba.se.impl.corba.RequestImpl;
 import com.sun.corba.se.impl.dynamicany.DynAnyFactoryImpl;
 import com.sun.corba.se.impl.encoding.EncapsOutputStream;
+import com.sun.corba.se.impl.encoding.CachedCodeBase;
 import com.sun.corba.se.impl.interceptors.PIHandlerImpl;
 import com.sun.corba.se.impl.interceptors.PINoOpHandlerImpl;
 import com.sun.corba.se.impl.ior.TaggedComponentFactoryFinderImpl;
@@ -185,6 +188,7 @@
 
     private java.lang.Object runObj = new java.lang.Object();
     private java.lang.Object shutdownObj = new java.lang.Object();
+    private java.lang.Object waitForCompletionObj = new java.lang.Object();
     private static final byte STATUS_OPERATING = 1;
     private static final byte STATUS_SHUTTING_DOWN = 2;
     private static final byte STATUS_SHUTDOWN = 3;
@@ -193,6 +197,7 @@
 
     // XXX Should we move invocation tracking to the first level server dispatcher?
     private java.lang.Object invocationObj = new java.lang.Object();
+    private int numInvocations = 0;
 
     // thread local variable to store a boolean to detect deadlock in
     // ORB.shutdown(true).
@@ -220,8 +225,6 @@
 
     private int transientServerId ;
 
-    private ThreadGroup threadGroup ;
-
     private ServiceContextRegistry serviceContextRegistry ;
 
     // Needed here to implement connect/disconnect
@@ -279,6 +282,8 @@
 
     private ObjectKeyFactory objectKeyFactory ;
 
+    private boolean orbOwnsThreadPoolManager = false ;
+
     private ThreadPoolManager threadpoolMgr;
 
     private void dprint( String msg )
@@ -322,11 +327,17 @@
 
     public ORBVersion getORBVersion()
     {
+        synchronized (this) {
+                checkShutdownState();
+        }
         return (ORBVersion)(orbVersionThreadLocal.get()) ;
     }
 
     public void setORBVersion(ORBVersion verObj)
     {
+        synchronized (this) {
+                checkShutdownState();
+        }
         orbVersionThreadLocal.set(verObj);
     }
 
@@ -347,46 +358,6 @@
         // end of this method.
         pihandler = new PINoOpHandlerImpl( );
 
-        // See bugs 4916766 and 4936203
-        // We intend to create new threads in a reliable thread group.
-        // This avoids problems if the application/applet
-        // creates a thread group, makes JavaIDL calls which create a new
-        // connection and ReaderThread, and then destroys the thread
-        // group. If our ReaderThreads were to be part of such destroyed thread
-        // group then it might get killed and cause other invoking threads
-        // sharing the same connection to get a non-restartable
-        // CommunicationFailure. We'd like to avoid that.
-        //
-        // Our solution is to create all of our threads in the highest thread
-        // group that we have access to, given our own security clearance.
-        //
-        try {
-            // try to get a thread group that's as high in the threadgroup
-            // parent-child hierarchy, as we can get to.
-            // this will prevent an ORB thread created during applet-init from
-            // being killed when an applet dies.
-            threadGroup = (ThreadGroup) AccessController.doPrivileged(
-                new PrivilegedAction() {
-                    public Object run() {
-                        ThreadGroup tg = Thread.currentThread().getThreadGroup() ;
-                        ThreadGroup ptg = tg ;
-                        try {
-                            while (ptg != null) {
-                                tg = ptg;
-                                ptg = tg.getParent();
-                            }
-                        } catch (SecurityException se) {
-                            // Discontinue going higher on a security exception.
-                        }
-                        return new ThreadGroup(tg, "ORB ThreadGroup");
-                    }
-                }
-            );
-        } catch (SecurityException e) {
-            // something wrong, we go back to the original code
-            threadGroup = Thread.currentThread().getThreadGroup();
-        }
-
         // This is the unique id of this server (JVM). Multiple incarnations
         // of this server will get different ids.
         // Compute transientServerId = milliseconds since Jan 1, 1970
@@ -547,6 +518,9 @@
 
     public void set_parameters( Properties props )
     {
+        synchronized (this) {
+                checkShutdownState();
+        }
         preInit( null, props ) ;
         DataCollector dataCollector =
             DataCollectorFactory.create( props, getLocalHostName() ) ;
@@ -788,6 +762,9 @@
      */
     public void notifyORB()
     {
+        synchronized (this) {
+                checkShutdownState();
+        }
         synchronized (this.svResponseReceived) {
             this.svResponseReceived.set();
             this.svResponseReceived.notify();
@@ -854,6 +831,8 @@
     // Note that we connect this if we have not already done so.
     public synchronized IOR getFVDCodeBaseIOR()
     {
+        checkShutdownState();
+
         if (codeBaseIOR != null) // i.e. We are already connected to it
             return codeBaseIOR;
 
@@ -1118,6 +1097,8 @@
 
     public synchronized void setTypeCodeForClass(Class c, TypeCodeImpl tci)
     {
+        checkShutdownState();
+
         if (typeCodeForClassMap == null)
             typeCodeForClassMap = Collections.synchronizedMap(
                 new WeakHashMap(64));
@@ -1128,6 +1109,8 @@
 
     public synchronized TypeCodeImpl getTypeCodeForClass(Class c)
     {
+        checkShutdownState();
+
         if (typeCodeForClassMap == null)
             return null;
         return (TypeCodeImpl)typeCodeForClassMap.get(c);
@@ -1210,6 +1193,10 @@
     {
         CorbaServerRequestDispatcher insnd ;
 
+        synchronized (this) {
+            checkShutdownState();
+        }
+
         if ((id == null) || (id.length() == 0))
             throw new InvalidName() ;
 
@@ -1253,66 +1240,88 @@
         }
     }
 
-    public void shutdown(boolean wait_for_completion)
-    {
-        // to wait for completion, we would deadlock, so throw a standard
-        // OMG exception.
-        if (wait_for_completion && ((Boolean)isProcessingInvocation.get()).booleanValue()) {
-	    throw omgWrapper.shutdownWaitForCompletionDeadlock() ;
-        }
-
-        boolean doShutdown = false ;
+    public void shutdown(boolean wait_for_completion) {
+        boolean wait = false;
 
         synchronized (this) {
-	    checkShutdownState() ;
+            checkShutdownState();
 
-	    if (status == STATUS_SHUTTING_DOWN) {
-	        if (!wait_for_completion)
-		// If we are already shutting down and don't want
-		// to wait, nothing to do: return.
-		return ;
-	    } else {
-	        // The ORB status was STATUS_OPERATING, so start the shutdown.
-	        status = STATUS_SHUTTING_DOWN ;
-	        doShutdown = true ;
-	    }
-        }
-	
-        // At this point, status is SHUTTING_DOWN.
-        // All shutdown calls with wait_for_completion == true must synchronize
-        // here.  Only the first call will be made with doShutdown == true.
+            // This is to avoid deadlock: don't allow a thread that is
+            // processing a request to call shutdown( true ), because
+            // the shutdown would block waiting for the request to complete,
+            // while the request would block waiting for shutdown to complete.
+            if (wait_for_completion &&
+                isProcessingInvocation.get() == Boolean.TRUE) {
+                throw omgWrapper.shutdownWaitForCompletionDeadlock();
+            }
+
+            if (status == STATUS_SHUTTING_DOWN) {
+                if (wait_for_completion) {
+                    wait = true;
+                } else {
+                    return;
+                }
+            }
+
+            status = STATUS_SHUTTING_DOWN;
+       }
+
+        // Avoid more than one thread performing shutdown at a time.
         synchronized (shutdownObj) {
-	    if (doShutdown) {
-	        // shutdownServants will set all POAManagers into the
-	        // INACTIVE state, causing request to be rejected.
-	        // If wait_for_completion is true, this will not return until
-	        // all invocations have completed.
-	        shutdownServants(wait_for_completion);
+            // At this point, the ORB status is certainly STATUS_SHUTTING_DOWN.
+            // If wait is true, another thread already called shutdown( true ),
+            // and so we wait for completion
+            if (wait) {
+                while (true) {
+                    synchronized (this) {
+                        if (status == STATUS_SHUTDOWN)
+                            break;
+                    }
+
+                    try {
+                        shutdownObj.wait();
+                    } catch (InterruptedException exc) {
+                        // NOP: just loop and wait until state is changed
+                    }
+                }
+            } else {
+                // perform the actual shutdown
+                shutdownServants(wait_for_completion);
+
+                if (wait_for_completion) {
+                    synchronized ( waitForCompletionObj ) {
+                        while (numInvocations > 0) {
+                            try {
+                                waitForCompletionObj.wait();
+                            } catch (InterruptedException ex) {}
+                        }
+                    }
+                }
     
 	        synchronized (runObj) {
 		    runObj.notifyAll();
 	        }
 	    	
-	        synchronized (this) {
-		    status = STATUS_SHUTDOWN;
-	        }
+                status = STATUS_SHUTDOWN;
+
+                shutdownObj.notifyAll();
 	    }
         }
     }
 
-    /** This method shuts down the ORB and causes orb.run() to return.
-     *  It will cause all POAManagers to be deactivated, which in turn
-     *  will cause all POAs to be deactivated.
-     */
+    // Cause all ObjectAdapaterFactories to clean up all of their internal state, which
+    // may include activated objects that have associated state and callbacks that must
+    // complete in order to shutdown.  This will cause new request to be rejected.
     protected void shutdownServants(boolean wait_for_completion) {
-        Iterator iter = requestDispatcherRegistry.getObjectAdapterFactories().iterator() ;
-        while (iter.hasNext()) {
-            ObjectAdapterFactory oaf = (ObjectAdapterFactory)iter.next() ;
-            oaf.shutdown( wait_for_completion ) ;
+        Set<ObjectAdapterFactory> oaset;
+        synchronized (this) {
+            oaset = new HashSet<ObjectAdapterFactory>(requestDispatcherRegistry.getObjectAdapterFactories());
         }
+
+        for (ObjectAdapterFactory oaf : oaset)
+            oaf.shutdown(wait_for_completion);
     }
 
-    // REVISIT: was protected - made public for framework
     // Note that the caller must hold the ORBImpl lock.
     public void checkShutdownState()
     {
@@ -1327,21 +1336,40 @@
 
     public boolean isDuringDispatch()
     {
+        synchronized (this) {
+                checkShutdownState();
+        }
         Boolean value = (Boolean)(isProcessingInvocation.get()) ;
         return value.booleanValue() ;
     }
 
     public void startingDispatch()
     {
+        synchronized (this) {
+                checkShutdownState();
+        }
         synchronized (invocationObj) {
             isProcessingInvocation.set(Boolean.TRUE);
+            numInvocations++;
         }
     }
 
     public void finishedDispatch()
     {
+        synchronized (this) {
+                checkShutdownState();
+        }
         synchronized (invocationObj) {
-            isProcessingInvocation.set(Boolean.FALSE);
+            numInvocations--;
+            isProcessingInvocation.set(false);
+            if (numInvocations == 0) {
+                synchronized (waitForCompletionObj) {
+                    waitForCompletionObj.notifyAll();
+                }
+            } else if (numInvocations < 0) {
+                throw wrapper.numInvocationsAlreadyZero(
+                    CompletionStatus.COMPLETED_YES);
+            }
         }
     }
 
@@ -1350,12 +1378,12 @@
      *  not been shut down, it will start the shutdown process and block until
      *  the ORB has shut down before it destroys the ORB."
      */
-    public synchronized void destroy()
+    public void destroy()
     {
-	boolean shutdownFirst = false ;
+        boolean shutdownFirst = false;
 
 	synchronized (this) {
-	    shutdownFirst = (status == STATUS_OPERATING) ;
+            shutdownFirst = (status == STATUS_OPERATING);
 	}
 
 	if (shutdownFirst) {
@@ -1365,11 +1393,76 @@
         synchronized (this) {
 	    if (status < STATUS_DESTROYED) {
 		getCorbaTransportManager().close();
-		getPIHandler().destroyInterceptors() ;
+                getPIHandler().destroyInterceptors();
 		status = STATUS_DESTROYED;
 	    }
 	}
+        synchronized (threadPoolManagerAccessLock) {
+            if (orbOwnsThreadPoolManager) {
+                try {
+                    threadpoolMgr.close();
+                    threadpoolMgr = null;
+                } catch (IOException exc) {
+                    wrapper.ioExceptionOnClose(exc);
+                }
+            }
+        }
+
+        try {
+            monitoringManager.close();
+            monitoringManager = null;
+        } catch (IOException exc) {
+            wrapper.ioExceptionOnClose(exc);
+        }
 
+        CachedCodeBase.cleanCache(this);
+        try {
+            pihandler.close();
+        } catch (IOException exc) {
+            wrapper.ioExceptionOnClose(exc);
+        }
+
+        super.destroy();
+
+        badServerIdHandlerAccessLock = null;
+        clientDelegateFactoryAccessorLock = null;
+        corbaContactInfoListFactoryAccessLock = null;
+
+        objectKeyFactoryAccessLock = null;
+        legacyServerSocketManagerAccessLock = null;
+        threadPoolManagerAccessLock = null;
+        transportManager = null;
+        legacyServerSocketManager = null;
+        OAInvocationInfoStack  = null;
+        clientInvocationInfoStack  = null;
+        codeBaseIOR = null;
+        dynamicRequests  = null;
+        svResponseReceived  = null;
+        runObj = null;
+        shutdownObj = null;
+        waitForCompletionObj = null;
+        invocationObj = null;
+        isProcessingInvocation = null;
+        typeCodeForClassMap  = null;
+        valueFactoryCache = null;
+        orbVersionThreadLocal = null;
+        requestDispatcherRegistry = null;
+        copierManager = null;
+        toaFactory = null;
+        poaFactory = null;
+        pihandler = null;
+        configData = null;
+        badServerIdHandler = null;
+        clientDelegateFactory = null;
+        corbaContactInfoListFactory = null;
+        resolver = null;
+        localResolver = null;
+        insNamingDelegate = null;
+        urlOperation = null;
+        taggedComponentFactoryFinder = null;
+        taggedProfileFactoryFinder = null;
+        taggedProfileTemplateFactoryFinder = null;
+        objectKeyFactory = null;
     }
 
     /**
@@ -1434,18 +1527,27 @@
 
     public OAInvocationInfo peekInvocationInfo()
     {
+        synchronized (this) {
+                checkShutdownState();
+        }
         StackImpl stack = (StackImpl)(OAInvocationInfoStack.get()) ;
         return (OAInvocationInfo)(stack.peek()) ;
     }
 
     public void pushInvocationInfo( OAInvocationInfo info )
     {
+        synchronized (this) {
+                checkShutdownState();
+        }
         StackImpl stack = (StackImpl)(OAInvocationInfoStack.get()) ;
         stack.push( info ) ;
     }
 
     public OAInvocationInfo popInvocationInfo()
     {
+        synchronized (this) {
+                checkShutdownState();
+        }
         StackImpl stack = (StackImpl)(OAInvocationInfoStack.get()) ;
         return (OAInvocationInfo)(stack.pop()) ;
     }
@@ -1459,6 +1561,9 @@
 
     public void initBadServerIdHandler()
     {
+        synchronized (this) {
+                checkShutdownState();
+        }
         synchronized (badServerIdHandlerAccessLock) {
             Class cls = configData.getBadServerIdHandler() ;
             if (cls != null) {
@@ -1477,6 +1582,9 @@
 
     public void setBadServerIdHandler( BadServerIdHandler handler )
     {
+        synchronized (this) {
+                checkShutdownState();
+        }
         synchronized (badServerIdHandlerAccessLock) {
             badServerIdHandler = handler;
         }
@@ -1484,6 +1592,9 @@
 
     public void handleBadServerId( ObjectKey okey )
     {
+        synchronized (this) {
+                checkShutdownState();
+        }
         synchronized (badServerIdHandlerAccessLock) {
             if (badServerIdHandler == null)
                 throw wrapper.badServerId() ;
@@ -1532,6 +1643,9 @@
 
     public int getTransientServerId()
     {
+        synchronized (this) {
+                checkShutdownState();
+        }
         if( configData.getORBServerIdPropertySpecified( ) ) {
             // ORBServerId is specified then use that value
             return configData.getPersistentServerId( );
@@ -1541,11 +1655,17 @@
 
     public RequestDispatcherRegistry getRequestDispatcherRegistry()
     {
+        synchronized (this) {
+                checkShutdownState();
+        }
         return requestDispatcherRegistry;
     }
 
     public ServiceContextRegistry getServiceContextRegistry()
     {
+        synchronized (this) {
+                checkShutdownState();
+        }
         return serviceContextRegistry ;
     }
 
@@ -1563,12 +1683,18 @@
     // XXX What about multi-homed host?
     public boolean isLocalHost( String hostName )
     {
+        synchronized (this) {
+                checkShutdownState();
+        }
         return hostName.equals( configData.getORBServerHost() ) ||
             hostName.equals( getLocalHostName() ) ;
     }
 
     public boolean isLocalServerId( int subcontractId, int serverId )
     {
+        synchronized (this) {
+                checkShutdownState();
+        }
         if ((subcontractId < ORBConstants.FIRST_POA_SCID) ||
             (subcontractId > ORBConstants.MAX_POA_SCID))
             return serverId == getTransientServerId( ) ;
@@ -1659,6 +1785,9 @@
 
     public ClientInvocationInfo createOrIncrementInvocationInfo()
     {
+        synchronized (this) {
+                checkShutdownState();
+        }
         StackImpl invocationInfoStack =
             (StackImpl) clientInvocationInfoStack.get();
         ClientInvocationInfo clientInvocationInfo = null;
@@ -1682,10 +1811,13 @@
 
     public void releaseOrDecrementInvocationInfo()
     {
-        StackImpl invocationInfoStack =
-            (StackImpl)clientInvocationInfoStack.get();
+        synchronized (this) {
+                checkShutdownState();
+        }
         int entryCount = -1;
         ClientInvocationInfo clientInvocationInfo = null;
+        StackImpl invocationInfoStack =
+            (StackImpl)clientInvocationInfoStack.get();
         if (!invocationInfoStack.empty()) {
             clientInvocationInfo =
                 (ClientInvocationInfo)invocationInfoStack.peek();
@@ -1705,6 +1837,9 @@
 
     public ClientInvocationInfo getInvocationInfo()
     {
+        synchronized (this) {
+                checkShutdownState();
+        }
         StackImpl invocationInfoStack =
             (StackImpl) clientInvocationInfoStack.get();
         return (ClientInvocationInfo) invocationInfoStack.peek();
@@ -1719,6 +1854,9 @@
 
     public void setClientDelegateFactory( ClientDelegateFactory factory )
     {
+        synchronized (this) {
+                checkShutdownState();
+        }
         synchronized (clientDelegateFactoryAccessorLock) {
             clientDelegateFactory = factory ;
         }
@@ -1726,6 +1864,9 @@
 
     public ClientDelegateFactory getClientDelegateFactory()
     {
+        synchronized (this) {
+                checkShutdownState();
+        }
         synchronized (clientDelegateFactoryAccessorLock) {
             return clientDelegateFactory ;
         }
@@ -1735,6 +1876,9 @@
 
     public void setCorbaContactInfoListFactory( CorbaContactInfoListFactory factory )
     {
+        synchronized (this) {
+                checkShutdownState();
+        }
         synchronized (corbaContactInfoListFactoryAccessLock) {
             corbaContactInfoListFactory = factory ;
         }
@@ -1742,6 +1886,7 @@
 
     public synchronized CorbaContactInfoListFactory getCorbaContactInfoListFactory()
     {
+        checkShutdownState();
         return corbaContactInfoListFactory ;
     }
 
@@ -1750,6 +1895,9 @@
      */
     public void setResolver( Resolver resolver )
     {
+        synchronized (this) {
+                checkShutdownState();
+        }
         synchronized (resolverLock) {
             this.resolver = resolver ;
         }
@@ -1760,6 +1908,9 @@
      */
     public Resolver getResolver()
     {
+        synchronized (this) {
+                checkShutdownState();
+        }
         synchronized (resolverLock) {
             return resolver ;
         }
@@ -1770,6 +1921,9 @@
      */
     public void setLocalResolver( LocalResolver resolver )
     {
+        synchronized (this) {
+                checkShutdownState();
+        }
         synchronized (resolverLock) {
             this.localResolver = resolver ;
         }
@@ -1780,6 +1934,9 @@
      */
     public LocalResolver getLocalResolver()
     {
+        synchronized (this) {
+                checkShutdownState();
+        }
         synchronized (resolverLock) {
             return localResolver ;
         }
@@ -1790,6 +1947,9 @@
      */
     public void setURLOperation( Operation stringToObject )
     {
+        synchronized (this) {
+                checkShutdownState();
+        }
         synchronized (urlOperationLock) {
             urlOperation = stringToObject ;
         }
@@ -1800,6 +1960,9 @@
      */
     public Operation getURLOperation()
     {
+        synchronized (this) {
+                checkShutdownState();
+        }
         synchronized (urlOperationLock) {
             return urlOperation ;
         }
@@ -1807,6 +1970,9 @@
 
     public void setINSDelegate( CorbaServerRequestDispatcher sdel )
     {
+        synchronized (this) {
+                checkShutdownState();
+        }
         synchronized (resolverLock) {
             insNamingDelegate = sdel ;
         }
@@ -1814,16 +1980,25 @@
 
     public TaggedComponentFactoryFinder getTaggedComponentFactoryFinder()
     {
+        synchronized (this) {
+                checkShutdownState();
+        }
         return taggedComponentFactoryFinder ;
     }
 
     public IdentifiableFactoryFinder getTaggedProfileFactoryFinder()
     {
+        synchronized (this) {
+                checkShutdownState();
+        }
         return taggedProfileFactoryFinder ;
     }
 
     public IdentifiableFactoryFinder getTaggedProfileTemplateFactoryFinder()
     {
+        synchronized (this) {
+                checkShutdownState();
+        }
         return taggedProfileTemplateFactoryFinder ;
     }
 
@@ -1831,6 +2006,9 @@
 
     public ObjectKeyFactory getObjectKeyFactory()
     {
+        synchronized (this) {
+                checkShutdownState();
+        }
         synchronized (objectKeyFactoryAccessLock) {
             return objectKeyFactory ;
         }
@@ -1838,6 +2016,9 @@
 
     public void setObjectKeyFactory( ObjectKeyFactory factory )
     {
+        synchronized (this) {
+                checkShutdownState();
+        }
         synchronized (objectKeyFactoryAccessLock) {
             objectKeyFactory = factory ;
         }
@@ -1864,6 +2045,9 @@
 
     public LegacyServerSocketManager getLegacyServerSocketManager()
     {
+        synchronized (this) {
+                checkShutdownState();
+        }
         synchronized (legacyServerSocketManagerAccessLock) {
             if (legacyServerSocketManager == null) {
                 legacyServerSocketManager = new LegacyServerSocketManagerImpl(this);
@@ -1876,6 +2060,9 @@
 
     public void setThreadPoolManager(ThreadPoolManager mgr)
     {
+        synchronized (this) {
+                checkShutdownState();
+        }
         synchronized (threadPoolManagerAccessLock) {
             threadpoolMgr = mgr;
         }
@@ -1883,9 +2070,13 @@
 
     public ThreadPoolManager getThreadPoolManager()
     {
+        synchronized (this) {
+                checkShutdownState();
+        }
         synchronized (threadPoolManagerAccessLock) {
             if (threadpoolMgr == null) {
-                threadpoolMgr = new ThreadPoolManagerImpl( threadGroup );
+                threadpoolMgr = new ThreadPoolManagerImpl();
+                orbOwnsThreadPoolManager = true;
             }
             return threadpoolMgr;
         }
@@ -1893,6 +2084,9 @@
 
     public CopierManager getCopierManager()
     {
+        synchronized (this) {
+                checkShutdownState();
+        }
         return copierManager ;
     }
 } // Class ORBImpl
diff -Nru openjdk.orig/corba/src/share/classes/com/sun/corba/se/impl/orbutil/threadpool/ThreadPoolImpl.java openjdk/corba/src/share/classes/com/sun/corba/se/impl/orbutil/threadpool/ThreadPoolImpl.java
--- openjdk.orig/corba/src/share/classes/com/sun/corba/se/impl/orbutil/threadpool/ThreadPoolImpl.java	2012-10-26 19:21:48.000000000 +0100
+++ openjdk/corba/src/share/classes/com/sun/corba/se/impl/orbutil/threadpool/ThreadPoolImpl.java	2013-02-13 16:50:31.281776428 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -25,6 +25,18 @@
 
 package com.sun.corba.se.impl.orbutil.threadpool;
 
+import java.io.IOException;
+import java.io.Closeable;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+import java.util.List;
+import java.util.ArrayList;
+
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+
 import com.sun.corba.se.spi.orbutil.threadpool.NoSuchWorkQueueException;
 import com.sun.corba.se.spi.orbutil.threadpool.ThreadPool;
 import com.sun.corba.se.spi.orbutil.threadpool.Work;
@@ -36,12 +48,27 @@
 import com.sun.corba.se.spi.monitoring.MonitoringConstants;
 import com.sun.corba.se.spi.monitoring.MonitoredObject;
 import com.sun.corba.se.spi.monitoring.MonitoringFactories;
+import com.sun.corba.se.spi.orb.ORB;
 import com.sun.corba.se.spi.monitoring.LongMonitoredAttributeBase;
 
+import com.sun.corba.se.impl.logging.ORBUtilSystemException;
+import com.sun.corba.se.impl.orbutil.ORBConstants;
+import com.sun.corba.se.spi.logging.CORBALogDomains;
+
 public class ThreadPoolImpl implements ThreadPool
 {
-    private static int threadCounter = 0; // serial counter useful for debugging
+    // serial counter useful for debugging
+    private static AtomicInteger threadCounter = new AtomicInteger(0);
+    private static final ORBUtilSystemException wrapper =
+        ORBUtilSystemException.get(CORBALogDomains.RPC_TRANSPORT);
+
 
+    // Any time currentThreadCount and/or availableWorkerThreads is updated
+    // or accessed this ThreadPool's WorkQueue must be locked. And, it is
+    // expected that this ThreadPool's WorkQueue is the only object that
+    // updates and accesses these values directly and indirectly though a
+    // call to a method in this ThreadPool. If any call to update or access
+    // those values must synchronized on this ThreadPool's WorkQueue.
     private WorkQueue workQueue;
 
     // Stores the number of available worker threads
@@ -65,14 +92,11 @@
     // Running count of the work items processed
     // Set the value to 1 so that divide by zero is avoided in
     // averageWorkCompletionTime()
-    private long processedCount = 1;
+    private AtomicLong processedCount = new AtomicLong(1);
 
     // Running aggregate of the time taken in millis to execute work items
     // processed by the threads in the threadpool
-    private long totalTimeTaken = 0;
-
-    // Lock for protecting state when required
-    private Object lock = new Object();
+    private AtomicLong totalTimeTaken = new AtomicLong(0);
 
     // Name of the ThreadPool
     private String name;
@@ -81,7 +105,10 @@
     private MonitoredObject threadpoolMonitoredObject;
 
     // ThreadGroup in which threads should be created
-    private ThreadGroup threadGroup ;
+    private ThreadGroup threadGroup;
+
+    Object workersLock = new Object();
+    List<WorkerThread> workers = new ArrayList<WorkerThread>();
 
     /**
      * This constructor is used to create an unbounded threadpool
@@ -90,7 +117,7 @@
         inactivityTimeout = ORBConstants.DEFAULT_INACTIVITY_TIMEOUT;
         maxWorkerThreads = Integer.MAX_VALUE;
         workQueue = new WorkQueueImpl(this);
-        threadGroup = tg ;
+        threadGroup = tg;
         name = threadpoolName;
         initializeMonitoring();
     }
@@ -121,6 +148,30 @@
         initializeMonitoring();
     }
 
+    // Note that this method should not return until AFTER all threads have died.
+    public void close() throws IOException {
+
+        // Copy to avoid concurrent modification problems.
+        List<WorkerThread> copy = null;
+        synchronized (workersLock) {
+            copy = new ArrayList<WorkerThread>(workers);
+        }
+
+        for (WorkerThread wt : copy) {
+            wt.close();
+            while (wt.getState() != Thread.State.TERMINATED) {
+                try {
+                    wt.join();
+                } catch (InterruptedException exc) {
+                    wrapper.interruptedJoinCallWhileClosingThreadPool(exc, wt, this);
+                }
+            }
+        }
+
+        threadGroup = null;
+    }
+
+
     // Setup monitoring for this threadpool
     private void initializeMonitoring() {
         // Get root monitored object
@@ -217,8 +268,8 @@
      * or notify waiting threads on the queue for available work
      */
     void notifyForAvailableWork(WorkQueue aWorkQueue) {
-        synchronized (lock) {
-            if (availableWorkerThreads == 0) {
+        synchronized (aWorkQueue) {
+            if (availableWorkerThreads < aWorkQueue.workItemsInQueue()) {
                 createWorkerThread();
             } else {
                 aWorkQueue.notify();
@@ -227,120 +278,145 @@
     }
 
 
-    /**
-     * To be called from the workqueue to create worker threads when none
-     * available.
-     */
-    void createWorkerThread() {
-        WorkerThread thread;
-
-        synchronized (lock) {
-            if (boundedThreadPool) {
-                if (currentThreadCount < maxWorkerThreads) {
-                    thread = new WorkerThread(threadGroup, getName());
-                    currentThreadCount++;
-                } else {
-                    // REVIST - Need to create a thread to monitor the
-                    // the state for deadlock i.e. all threads waiting for
-                    // something which can be got from the item in the
-                    // workqueue, but there is no thread available to
-                    // process that work item - DEADLOCK !!
-                    return;
-                }
-            } else {
-                thread = new WorkerThread(threadGroup, getName());
-                currentThreadCount++;
-            }
+    private Thread createWorkerThreadHelper( String name ) {
+        // Thread creation needs to be in a doPrivileged block
+        // if there is a non-null security manager for two reasons:
+        // 1. The creation of a thread in a specific ThreadGroup
+        //    is a privileged operation.  Lack of a doPrivileged
+        //    block here causes an AccessControlException
+        //    (see bug 6268145).
+        // 2. We want to make sure that the permissions associated
+        //    with this thread do NOT include the permissions of
+        //    the current thread that is calling this method.
+        //    This leads to problems in the app server where
+        //    some threads in the ThreadPool randomly get
+        //    bad permissions, leading to unpredictable
+        //    permission errors (see bug 6021011).
+        //
+        //    A Java thread contains a stack of call frames,
+        //    one for each method called that has not yet returned.
+        //    Each method comes from a particular class.  The class
+        //    was loaded by a ClassLoader which has an associated
+        //    CodeSource, and this determines the Permissions
+        //    for all methods in that class.  The current
+        //    Permissions for the thread are the intersection of
+        //    all Permissions for the methods on the stack.
+        //    This is part of the Security Context of the thread.
+        //
+        //    When a thread creates a new thread, the new thread
+        //    inherits the security context of the old thread.
+        //    This is bad in a ThreadPool, because different
+        //    creators of threads may have different security contexts.
+        //    This leads to occasional unpredictable errors when
+        //    a thread is re-used in a different security context.
+        //
+        //    Avoiding this problem is simple: just do the thread
+        //    creation in a doPrivileged block.  This sets the
+        //    inherited security context to that of the code source
+        //    for the ORB code itself, which contains all permissions
+        //    in either Java SE or Java EE.
+        WorkerThread thread = new WorkerThread(threadGroup, name);
+        synchronized (workersLock) {
+            workers.add(thread);
         }
 
         // The thread must be set to a daemon thread so the
         // VM can exit if the only threads left are PooledThreads
         // or other daemons.  We don't want to rely on the
         // calling thread always being a daemon.
+        // Note that no exception is possible here since we
+        // are inside the doPrivileged block.
+        thread.setDaemon(true);
 
-        // Catch exceptions since setDaemon can cause a
-        // security exception to be thrown under netscape
-        // in the Applet mode
-        try {
-            thread.setDaemon(true);
-        } catch (Exception e) {
-            // REVISIT - need to do some logging here
-        }
+        wrapper.workerThreadCreated(thread, thread.getContextClassLoader());
 
         thread.start();
+        return null;
     }
 
+
     /**
-    * This method will return the minimum number of threads maintained
-    * by the threadpool.
-    */
+     * To be called from the workqueue to create worker threads when none
+     * available.
+     */
+    void createWorkerThread() {
+        final String name = getName();
+        synchronized (workQueue) {
+            try {
+                if (System.getSecurityManager() == null) {
+                    createWorkerThreadHelper(name);
+                } else {
+                    // If we get here, we need to create a thread.
+                    AccessController.doPrivileged(
+                            new PrivilegedAction() {
+                        public Object run() {
+                            return createWorkerThreadHelper(name);
+                        }
+                    }
+                    );
+                }
+            } catch (Throwable t) {
+                // Decrementing the count of current worker threads.
+                // But, it will be increased in the finally block.
+                decrementCurrentNumberOfThreads();
+                wrapper.workerThreadCreationFailure(t);
+            } finally {
+                incrementCurrentNumberOfThreads();
+            }
+        }
+    }
+
     public int minimumNumberOfThreads() {
         return minWorkerThreads;
     }
 
-    /**
-    * This method will return the maximum number of threads in the
-    * threadpool at any point in time, for the life of the threadpool
-    */
     public int maximumNumberOfThreads() {
         return maxWorkerThreads;
     }
 
-    /**
-    * This method will return the time in milliseconds when idle
-    * threads in the threadpool are removed.
-    */
     public long idleTimeoutForThreads() {
         return inactivityTimeout;
     }
 
-    /**
-    * This method will return the total number of threads currently in the
-    * threadpool. This method returns a value which is not synchronized.
-    */
     public int currentNumberOfThreads() {
-        synchronized (lock) {
+        synchronized (workQueue) {
             return currentThreadCount;
         }
     }
 
-    /**
-    * This method will return the number of available threads in the
-    * threadpool which are waiting for work. This method returns a
-    * value which is not synchronized.
-    */
+    void decrementCurrentNumberOfThreads() {
+        synchronized (workQueue) {
+            currentThreadCount--;
+        }
+    }
+
+    void incrementCurrentNumberOfThreads() {
+        synchronized (workQueue) {
+            currentThreadCount++;
+        }
+    }
+
     public int numberOfAvailableThreads() {
-        synchronized (lock) {
+        synchronized (workQueue) {
             return availableWorkerThreads;
         }
     }
 
-    /**
-    * This method will return the number of busy threads in the threadpool
-    * This method returns a value which is not synchronized.
-    */
     public int numberOfBusyThreads() {
-        synchronized (lock) {
+        synchronized (workQueue) {
             return (currentThreadCount - availableWorkerThreads);
         }
     }
 
-    /**
-     * This method returns the average elapsed time taken to complete a Work
-     * item in milliseconds.
-     */
     public long averageWorkCompletionTime() {
-        synchronized (lock) {
-            return (totalTimeTaken / processedCount);
+        synchronized (workQueue) {
+            return (totalTimeTaken.get() / processedCount.get());
         }
     }
 
-    /**
-     * This method returns the number of Work items processed by the threadpool
-     */
     public long currentProcessedCount() {
-        synchronized (lock) {
-            return processedCount;
+        synchronized (workQueue) {
+            return processedCount.get();
         }
     }
 
@@ -357,15 +433,37 @@
 
 
     private static synchronized int getUniqueThreadId() {
-        return ThreadPoolImpl.threadCounter++;
+        return ThreadPoolImpl.threadCounter.incrementAndGet();
+    }
+
+    /**
+     * This method will decrement the number of available threads
+     * in the threadpool which are waiting for work. Called from
+     * WorkQueueImpl.requestWork()
+     */
+    void decrementNumberOfAvailableThreads() {
+        synchronized (workQueue) {
+            availableWorkerThreads--;
+        }
+    }
+
+    /**
+     * This method will increment the number of available threads
+     * in the threadpool which are waiting for work. Called from
+     * WorkQueueImpl.requestWork()
+     */
+    void incrementNumberOfAvailableThreads() {
+        synchronized (workQueue) {
+            availableWorkerThreads++;
+        }
     }
 
 
-    private class WorkerThread extends Thread
+    private class WorkerThread extends Thread implements Closeable
     {
         private Work currentWork;
         private int threadId = 0; // unique id for the thread
-        // thread pool this WorkerThread belongs too
+        private volatile boolean closeCalled = false;
         private String threadPoolName;
         // name seen by Thread.getName()
         private StringBuffer workerThreadName = new StringBuffer();
@@ -377,100 +475,61 @@
             setName(composeWorkerThreadName(threadPoolName, "Idle"));
         }
 
-        public void run() {
-            while (true) {
-                try {
-
-                    synchronized (lock) {
-                        availableWorkerThreads++;
-                    }
-
-                    // Get some work to do
-                    currentWork = ((WorkQueueImpl)workQueue).requestWork(inactivityTimeout);
+        public synchronized void close() {
+            closeCalled = true;
+            interrupt();
+        }
 
-                    synchronized (lock) {
-                        availableWorkerThreads--;
-                        // It is possible in notifyForAvailableWork that the
-                        // check for availableWorkerThreads = 0 may return
-                        // false, because the availableWorkerThreads has not been
-                        // decremented to zero before the producer thread added
-                        // work to the queue. This may create a deadlock, if the
-                        // executing thread needs information which is in the work
-                        // item queued in the workqueue, but has no thread to work
-                        // on it since none was created because availableWorkerThreads = 0
-                        // returned false.
-                        // The following code will ensure that a thread is always available
-                        // in those situations
-                        if  ((availableWorkerThreads == 0) &&
-                                (workQueue.workItemsInQueue() > 0)) {
-                            createWorkerThread();
-                        }
-                    }
+        private void resetClassLoader() {
 
-                    // Set the thread name for debugging.
-                    setName(composeWorkerThreadName(threadPoolName,
-                                      Integer.toString(this.threadId)));
+        }
 
-                    long start = System.currentTimeMillis();
+        private void performWork() {
+            long start = System.currentTimeMillis();
+            try {
+                currentWork.doWork();
+            } catch (Throwable t) {
+                wrapper.workerThreadDoWorkThrowable(this, t);
+            }
+            long elapsedTime = System.currentTimeMillis() - start;
+            totalTimeTaken.addAndGet(elapsedTime);
+            processedCount.incrementAndGet();
+        }
 
+        public void run() {
+            try  {
+                while (!closeCalled) {
                     try {
-                        // Do the work
-                        currentWork.doWork();
-                    } catch (Throwable t) {
-                        // Ignore all errors.
-                        ;
-                    }
-
-                    long end = System.currentTimeMillis();
+                        currentWork = ((WorkQueueImpl)workQueue).requestWork(
+                            inactivityTimeout);
+                        if (currentWork == null)
+                            continue;
+                    } catch (InterruptedException exc) {
+                        wrapper.workQueueThreadInterrupted( exc, getName(),
+                           Boolean.valueOf(closeCalled));
 
+                        continue ;
+                    } catch (Throwable t) {
+                         wrapper.workerThreadThrowableFromRequestWork(this, t,
+                                workQueue.getName());
 
-                    synchronized (lock) {
-                        totalTimeTaken += (end - start);
-                        processedCount++;
+                        continue;
                     }
 
+                    performWork();
+
                     // set currentWork to null so that the work item can be
-                    // garbage collected
+                    // garbage collected without waiting for the next work item.
                     currentWork = null;
 
-                    setName(composeWorkerThreadName(threadPoolName, "Idle"));
-
-                } catch (TimeoutException e) {
-                    // This thread timed out waiting for something to do.
-
-                    synchronized (lock) {
-                        availableWorkerThreads--;
-
-                        // This should for both bounded and unbounded case
-                        if (currentThreadCount > minWorkerThreads) {
-                            currentThreadCount--;
-                            // This thread can exit.
-                            return;
-                        } else {
-                            // Go back to waiting on workQueue
-                            continue;
-                        }
-                    }
-                } catch (InterruptedException ie) {
-                    // InterruptedExceptions are
-                    // caught here.  Thus, threads can be forced out of
-                    // requestWork and so they have to reacquire the lock.
-                    // Other options include ignoring or
-                    // letting this thread die.
-                    // Ignoring for now. REVISIT
-                    synchronized (lock) {
-                        availableWorkerThreads--;
-                    }
-
-                } catch (Throwable e) {
-
-                    // Ignore any exceptions that currentWork.process
-                    // accidently lets through, but let Errors pass.
-                    // Add debugging output?  REVISIT
-                    synchronized (lock) {
-                        availableWorkerThreads--;
-                    }
-
+                    resetClassLoader();
+                }
+            } catch (Throwable e) {
+                // This should not be possible
+                wrapper.workerThreadCaughtUnexpectedThrowable(this,e);
+            } finally {
+                synchronized (workersLock) {
+                    workers.remove(this);
                 }
             }
         }
diff -Nru openjdk.orig/corba/src/share/classes/com/sun/corba/se/impl/orbutil/threadpool/ThreadPoolManagerImpl.java openjdk/corba/src/share/classes/com/sun/corba/se/impl/orbutil/threadpool/ThreadPoolManagerImpl.java
--- openjdk.orig/corba/src/share/classes/com/sun/corba/se/impl/orbutil/threadpool/ThreadPoolManagerImpl.java	2012-10-26 19:21:48.000000000 +0100
+++ openjdk/corba/src/share/classes/com/sun/corba/se/impl/orbutil/threadpool/ThreadPoolManagerImpl.java	2013-02-13 16:50:31.281776428 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -25,6 +25,15 @@
 
 package com.sun.corba.se.impl.orbutil.threadpool;
 
+import java.io.IOException;
+
+import java.security.PrivilegedAction;
+import java.security.AccessController;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import com.sun.corba.se.spi.orb.ORB;
+
 import com.sun.corba.se.spi.orbutil.threadpool.NoSuchThreadPoolException;
 import com.sun.corba.se.spi.orbutil.threadpool.ThreadPool;
 import com.sun.corba.se.spi.orbutil.threadpool.ThreadPoolManager;
@@ -33,21 +42,102 @@
 import com.sun.corba.se.impl.orbutil.threadpool.ThreadPoolImpl;
 import com.sun.corba.se.impl.orbutil.ORBConstants;
 
+import com.sun.corba.se.impl.logging.ORBUtilSystemException;
+import com.sun.corba.se.impl.orbutil.ORBConstants;
+import com.sun.corba.se.spi.logging.CORBALogDomains;
+
+
 public class ThreadPoolManagerImpl implements ThreadPoolManager
 {
-    private ThreadPool threadPool ;
+    private ThreadPool threadPool;
+    private ThreadGroup threadGroup;
+
+    private static final ORBUtilSystemException wrapper =
+        ORBUtilSystemException.get(CORBALogDomains.RPC_TRANSPORT);
+
+    public ThreadPoolManagerImpl() {
+        threadGroup = getThreadGroup();
+        threadPool = new ThreadPoolImpl(threadGroup,
+            ORBConstants.THREADPOOL_DEFAULT_NAME);
+    }
+
+    private static AtomicInteger tgCount = new AtomicInteger();
+
+
+    private ThreadGroup getThreadGroup() {
+        ThreadGroup tg;
+
+        // See bugs 4916766 and 4936203
+        // We intend to create new threads in a reliable thread group.
+        // This avoids problems if the application/applet
+        // creates a thread group, makes JavaIDL calls which create a new
+        // connection and ReaderThread, and then destroys the thread
+        // group. If our ReaderThreads were to be part of such destroyed thread
+        // group then it might get killed and cause other invoking threads
+        // sharing the same connection to get a non-restartable
+        // CommunicationFailure. We'd like to avoid that.
+        //
+        // Our solution is to create all of our threads in the highest thread
+        // group that we have access to, given our own security clearance.
+        //
+        try {
+            // try to get a thread group that's as high in the threadgroup
+            // parent-child hierarchy, as we can get to.
+            // this will prevent an ORB thread created during applet-init from
+            // being killed when an applet dies.
+            tg = AccessController.doPrivileged(
+                new PrivilegedAction<ThreadGroup>() {
+                    public ThreadGroup run() {
+                        ThreadGroup tg = Thread.currentThread().getThreadGroup();
+                        ThreadGroup ptg = tg;
+                        try {
+                            while (ptg != null) {
+                                tg = ptg;
+                                ptg = tg.getParent();
+                            }
+                        } catch (SecurityException se) {
+                            // Discontinue going higher on a security exception.
+                        }
+                        return new ThreadGroup(tg, "ORB ThreadGroup " + tgCount.getAndIncrement());
+                    }
+                }
+            );
+        } catch (SecurityException e) {
+            // something wrong, we go back to the original code
+            tg = Thread.currentThread().getThreadGroup();
+        }
+
+        return tg;
+    }
+
+    public void close() {
+        try {
+            threadPool.close();
+        } catch (IOException exc) {
+            wrapper.threadPoolCloseError();
+        }
+
+        try {
+            boolean isDestroyed = threadGroup.isDestroyed();
+            int numThreads = threadGroup.activeCount();
+            int numGroups = threadGroup.activeGroupCount();
+
+            if (isDestroyed) {
+                wrapper.threadGroupIsDestroyed(threadGroup);
+            } else {
+                if (numThreads > 0)
+                    wrapper.threadGroupHasActiveThreadsInClose(threadGroup, numThreads);
+
+                if (numGroups > 0)
+                    wrapper.threadGroupHasSubGroupsInClose(threadGroup, numGroups);
+
+                threadGroup.destroy();
+            }
+        } catch (IllegalThreadStateException exc) {
+            wrapper.threadGroupDestroyFailed(exc, threadGroup);
+        }
 
-    public ThreadPoolManagerImpl( ThreadGroup tg )
-    {
-        // Use unbounded threadpool in J2SE ORB
-        // ThreadPoolManager from s1as appserver code base can be set in the
-        // ORB. ThreadPools in the appserver are bounded. In that situation
-        // the ThreadPool in this ThreadPoolManager will have its threads
-        // die after the idle timeout.
-        // XXX Should there be cleanup when ORB.shutdown is called if the
-        // ORB owns the ThreadPool?
-        threadPool = new ThreadPoolImpl( tg,
-            ORBConstants.THREADPOOL_DEFAULT_NAME ) ;
+        threadGroup = null;
     }
 
     /**
diff -Nru openjdk.orig/corba/src/share/classes/com/sun/corba/se/impl/orbutil/threadpool/WorkQueueImpl.java openjdk/corba/src/share/classes/com/sun/corba/se/impl/orbutil/threadpool/WorkQueueImpl.java
--- openjdk.orig/corba/src/share/classes/com/sun/corba/se/impl/orbutil/threadpool/WorkQueueImpl.java	2012-10-26 19:21:48.000000000 +0100
+++ openjdk/corba/src/share/classes/com/sun/corba/se/impl/orbutil/threadpool/WorkQueueImpl.java	2013-02-13 16:50:31.281776428 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -111,24 +111,23 @@
         return workqueueMonitoredObject;
     }
 
-    public void addWork(Work work) {
-        synchronized (this) {
+    public synchronized void addWork(Work work) {
             workItemsAdded++;
             work.setEnqueueTime(System.currentTimeMillis());
             theWorkQueue.addLast(work);
             ((ThreadPoolImpl)workerThreadPool).notifyForAvailableWork(this);
-        }
     }
 
-    Work requestWork(long waitTime)
-        throws TimeoutException, InterruptedException
+    synchronized Work requestWork(long waitTime) throws TimeoutException, InterruptedException
     {
         Work workItem;
-        synchronized (this) {
+        ((ThreadPoolImpl)workerThreadPool).incrementNumberOfAvailableThreads();
+
             if (theWorkQueue.size() != 0) {
                 workItem = (Work)theWorkQueue.removeFirst();
                 totalTimeInQueue += System.currentTimeMillis() - workItem.getEnqueueTime();
                 workItemsDequeued++;
+                ((ThreadPoolImpl)workerThreadPool).decrementNumberOfAvailableThreads();
                 return workItem;
             }
 
@@ -145,6 +144,7 @@
                         workItem = (Work)theWorkQueue.removeFirst();
                         totalTimeInQueue += System.currentTimeMillis() - workItem.getEnqueueTime();
                         workItemsDequeued++;
+                        ((ThreadPoolImpl)workerThreadPool).decrementNumberOfAvailableThreads();
                         return workItem;
                     }
 
@@ -152,12 +152,13 @@
 
                 } while (remainingWaitTime > 0);
 
+                ((ThreadPoolImpl)workerThreadPool).decrementNumberOfAvailableThreads();
                 throw new TimeoutException();
 
             } catch (InterruptedException ie) {
+                ((ThreadPoolImpl)workerThreadPool).decrementNumberOfAvailableThreads();
                 throw ie;
             }
-        }
     }
 
     public void setThreadPool(ThreadPool workerThreadPool) {
diff -Nru openjdk.orig/corba/src/share/classes/com/sun/corba/se/impl/protocol/CorbaMessageMediatorImpl.java openjdk/corba/src/share/classes/com/sun/corba/se/impl/protocol/CorbaMessageMediatorImpl.java
--- openjdk.orig/corba/src/share/classes/com/sun/corba/se/impl/protocol/CorbaMessageMediatorImpl.java	2012-10-26 19:21:48.000000000 +0100
+++ openjdk/corba/src/share/classes/com/sun/corba/se/impl/protocol/CorbaMessageMediatorImpl.java	2013-02-13 16:50:31.281776428 +0000
@@ -1666,7 +1666,9 @@
         ((CDRInputObject)messageMediator.getInputObject()).unmarshalHeader();
 
         ORB orb = (ORB)messageMediator.getBroker();
-        orb.checkShutdownState();
+        synchronized (orb) {
+            orb.checkShutdownState();
+        }
 
         ObjectKey okey = messageMediator.getObjectKey();
         if (orb.subcontractDebugFlag) {
diff -Nru openjdk.orig/corba/src/share/classes/com/sun/corba/se/impl/transport/SelectorImpl.java openjdk/corba/src/share/classes/com/sun/corba/se/impl/transport/SelectorImpl.java
--- openjdk.orig/corba/src/share/classes/com/sun/corba/se/impl/transport/SelectorImpl.java	2012-10-26 19:21:49.000000000 +0100
+++ openjdk/corba/src/share/classes/com/sun/corba/se/impl/transport/SelectorImpl.java	2013-02-13 16:50:31.281776428 +0000
@@ -68,8 +68,8 @@
     private HashMap listenerThreads;
     private HashMap readerThreads;
     private boolean selectorStarted;
-    private boolean closed;
-    private ORBUtilSystemException wrapper ;
+    private volatile boolean closed;
+    private ORBUtilSystemException wrapper;
 
 
     public SelectorImpl(ORB orb)
diff -Nru openjdk.orig/corba/src/share/classes/com/sun/corba/se/spi/logging/data/ORBUtil.mc openjdk/corba/src/share/classes/com/sun/corba/se/spi/logging/data/ORBUtil.mc
--- openjdk.orig/corba/src/share/classes/com/sun/corba/se/spi/logging/data/ORBUtil.mc	2012-10-26 19:21:49.000000000 +0100
+++ openjdk/corba/src/share/classes/com/sun/corba/se/spi/logging/data/ORBUtil.mc	2013-02-13 16:50:31.285776492 +0000
@@ -1,6 +1,6 @@
 ;
 
-; Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
+; Copyright (c) 2003, 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
@@ -62,6 +62,7 @@
 	    (IS_LOCAL_REQUIRES_STUB 43 WARNING "Call to StubAdapter.isLocal did not pass a stub")
 	    (REQUEST_REQUIRES_STUB 44 WARNING "Call to StubAdapter.request did not pass a stub")
 	    (BAD_ACTIVATE_TIE_CALL 45 WARNING "Call to StubAdapter.activateTie did not pass a valid Tie")
+            (IO_EXCEPTION_ON_CLOSE 46 FINE "Useless exception on call to Closeable.close()")
 	    )
 	(BAD_PARAM
 	    (NULL_PARAM 1 WARNING "Null parameter")
@@ -291,7 +292,31 @@
 	    (JAVA_STREAM_INIT_FAILED 95 WARNING "Java stream initialization failed")
 	    (DUPLICATE_ORB_VERSION_SERVICE_CONTEXT 96 WARNING "An ORBVersionServiceContext was already in the service context list")
 	    (DUPLICATE_SENDING_CONTEXT_SERVICE_CONTEXT 97 WARNING "A SendingContextServiceContext was already in the service context list")
+            (WORK_QUEUE_THREAD_INTERRUPTED 98 FINE "Worker Thread from thread pool {0} was interrupted: closeCalled is {1}.")
+            (WORKER_THREAD_CREATED
+             104 FINE "Worker thread {0} has been created with ClassLoader {1}")
+            (WORKER_THREAD_THROWABLE_FROM_REQUEST_WORK
+             109 FINE "Worker thread {0} caught throwable {1} when requesting work from work queue {2}.")
+            (WORKER_THREAD_NOT_NEEDED
+             110 FINE "Worker thread {0} will exit; current thread count, {1}, greater than minunum worker threads needed, {2}.")
+            (WORKER_THREAD_DO_WORK_THROWABLE
+             111 FINE "Worker thread {0} caught throwable {1} while executing work.")
+            (WORKER_THREAD_CAUGHT_UNEXPECTED_THROWABLE
+             112 WARNING "Worker thread {0} caught unexpected throwable {1}.")
+            (WORKER_THREAD_CREATION_FAILURE
+             113 SEVERE "Worker thread creation failure; cause {0}.")
+            (WORKER_THREAD_SET_NAME_FAILURE
+             114 WARNING "Unable to set worker thread {0} name to {1}; cause {2}.")
+            (WORK_QUEUE_REQUEST_WORK_NO_WORK_FOUND
+             116 WARNING "Ignoring unexpected {0} when retrieving of work from work queue, {1}.")
+            (THREAD_POOL_CLOSE_ERROR 126 WARNING "Error in closing ThreadPool")
+            (THREAD_GROUP_IS_DESTROYED 127 WARNING "ThreadGroup {0} is already destroyed: can't destroy it")
+            (THREAD_GROUP_HAS_ACTIVE_THREADS_IN_CLOSE 128 WARNING "ThreadGroup {0} has {1} active threads: destroy may cause exception")
+            (THREAD_GROUP_HAS_SUB_GROUPS_IN_CLOSE 129 WARNING "ThreadGroup {0} has {1} sub-thread groups: destroy may cause exception")
+            (THREAD_GROUP_DESTROY_FAILED 130 WARNING "ThreadGroup {0} could not be destroyed")
+            (INTERRUPTED_JOIN_CALL_WHILE_CLOSING_THREAD_POOL 131 WARNING "Join was interrupted on thread {0} while closing ThreadPool {1}")
 	    )
+
 	(MARSHAL 
 	    (CHUNK_OVERFLOW 1 WARNING "Data read past end of chunk without closing the chunk")
 	    (UNEXPECTED_EOF 2 WARNING "Grow buffer strategy called underflow handler")
diff -Nru openjdk.orig/corba/src/share/classes/com/sun/corba/se/spi/monitoring/MonitoringManagerFactory.java openjdk/corba/src/share/classes/com/sun/corba/se/spi/monitoring/MonitoringManagerFactory.java
--- openjdk.orig/corba/src/share/classes/com/sun/corba/se/spi/monitoring/MonitoringManagerFactory.java	2012-10-26 19:21:49.000000000 +0100
+++ openjdk/corba/src/share/classes/com/sun/corba/se/spi/monitoring/MonitoringManagerFactory.java	2013-02-13 16:50:31.285776492 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -40,4 +40,6 @@
      */
     MonitoringManager createMonitoringManager( String nameOfTheRoot,
         String description );
+
+    void remove(String nameOfTheRoot);
 }
diff -Nru openjdk.orig/corba/src/share/classes/com/sun/corba/se/spi/monitoring/MonitoringManager.java openjdk/corba/src/share/classes/com/sun/corba/se/spi/monitoring/MonitoringManager.java
--- openjdk.orig/corba/src/share/classes/com/sun/corba/se/spi/monitoring/MonitoringManager.java	2012-10-26 19:21:49.000000000 +0100
+++ openjdk/corba/src/share/classes/com/sun/corba/se/spi/monitoring/MonitoringManager.java	2013-02-13 16:50:31.285776492 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -24,6 +24,7 @@
  */
 package com.sun.corba.se.spi.monitoring;
 
+import java.io.Closeable;
 import com.sun.corba.se.spi.orb.ORB;
 import com.sun.corba.se.spi.monitoring.MonitoredObject;
 import java.util.*;
@@ -39,7 +40,7 @@
  * @author Hemanth Puttaswamy
  * </p>
  */
-public interface MonitoringManager {
+public interface MonitoringManager extends Closeable {
 
   ///////////////////////////////////////
   // operations
diff -Nru openjdk.orig/corba/src/share/classes/com/sun/corba/se/spi/orb/ORB.java openjdk/corba/src/share/classes/com/sun/corba/se/spi/orb/ORB.java
--- openjdk.orig/corba/src/share/classes/com/sun/corba/se/spi/orb/ORB.java	2013-02-13 16:50:06.457377413 +0000
+++ openjdk/corba/src/share/classes/com/sun/corba/se/spi/orb/ORB.java	2013-02-13 16:51:31.034736868 +0000
@@ -172,7 +172,7 @@
 
     private static Map staticWrapperMap = new ConcurrentHashMap();
 
-    private MonitoringManager monitoringManager;
+    protected MonitoringManager monitoringManager;
 
     private static PresentationManager setupPresentationManager() {
         staticWrapper = ORBUtilSystemException.get(
@@ -221,6 +221,14 @@
         return pm;
     }
 
+    public void destroy() {
+        wrapper = null;
+        omgWrapper = null;
+        typeCodeMap = null;
+        primitiveTypeCodeConstants = null;
+        byteBufferPool = null;
+    }
+
     /**
      * Returns the Presentation Manager for the current thread group, using the ThreadGroup-specific 
      * AppContext to hold it. Creates and records one if needed.
@@ -306,6 +314,9 @@
     // Typecode support: needed in both ORBImpl and ORBSingleton
     public TypeCodeImpl get_primitive_tc(int kind)
     {
+        synchronized (this) {
+            checkShutdownState();
+        }
         try {
             return primitiveTypeCodeConstants[kind] ;
         } catch (Throwable t) {
@@ -315,15 +326,20 @@
 
     public synchronized void setTypeCode(String id, TypeCodeImpl code)
     {
+        checkShutdownState();
         typeCodeMap.put(id, code);
     }
 
     public synchronized TypeCodeImpl getTypeCode(String id)
     {
+        checkShutdownState();
         return (TypeCodeImpl)typeCodeMap.get(id);
     }
 
     public MonitoringManager getMonitoringManager( ) {
+        synchronized (this) {
+            checkShutdownState();
+        }
         return monitoringManager;
     }
 
@@ -438,6 +454,9 @@
      */
     public Logger getLogger( String domain )
     {
+        synchronized (this) {
+            checkShutdownState();
+        }
         ORBData odata = getORBData() ;
 
         // Determine the correct ORBId.  There are 3 cases:
@@ -514,6 +533,9 @@
     //       This method must also be inherited by both ORB and ORBSingleton.
     public ByteBufferPool getByteBufferPool()
     {
+        synchronized (this) {
+            checkShutdownState();
+        }
         if (byteBufferPool == null)
             byteBufferPool = new ByteBufferPoolImpl(this);
 
diff -Nru openjdk.orig/corba/src/share/classes/com/sun/corba/se/spi/orbutil/threadpool/ThreadPool.java openjdk/corba/src/share/classes/com/sun/corba/se/spi/orbutil/threadpool/ThreadPool.java
--- openjdk.orig/corba/src/share/classes/com/sun/corba/se/spi/orbutil/threadpool/ThreadPool.java	2012-10-26 19:21:49.000000000 +0100
+++ openjdk/corba/src/share/classes/com/sun/corba/se/spi/orbutil/threadpool/ThreadPool.java	2013-02-13 16:50:31.285776492 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -25,9 +25,15 @@
 
 package com.sun.corba.se.spi.orbutil.threadpool;
 
+import java.io.Closeable;
 
-public interface ThreadPool
+/** This interface defines a thread pool execution service.  The ORB uses this
+ * interface, which preceeds the JDK 5 ExecutorService.  Note that the close
+ * method must be called in order to reclaim thread resources.
+ */
+public interface ThreadPool extends Closeable
 {
+
     /**
     * This method will return any instance of the WorkQueue. If the ThreadPool
     * instance only services one WorkQueue then that WorkQueue instance will
diff -Nru openjdk.orig/corba/src/share/classes/com/sun/corba/se/spi/orbutil/threadpool/ThreadPoolManager.java openjdk/corba/src/share/classes/com/sun/corba/se/spi/orbutil/threadpool/ThreadPoolManager.java
--- openjdk.orig/corba/src/share/classes/com/sun/corba/se/spi/orbutil/threadpool/ThreadPoolManager.java	2012-10-26 19:21:49.000000000 +0100
+++ openjdk/corba/src/share/classes/com/sun/corba/se/spi/orbutil/threadpool/ThreadPoolManager.java	2013-02-13 16:50:31.285776492 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -25,7 +25,9 @@
 
 package com.sun.corba.se.spi.orbutil.threadpool;
 
-public interface ThreadPoolManager
+import java.io.Closeable;
+
+public interface ThreadPoolManager extends Closeable
 {
     /**
     * This method will return an instance of the threadpool given a threadpoolId,
diff -Nru openjdk.orig/corba/src/share/classes/com/sun/corba/se/spi/protocol/PIHandler.java openjdk/corba/src/share/classes/com/sun/corba/se/spi/protocol/PIHandler.java
--- openjdk.orig/corba/src/share/classes/com/sun/corba/se/spi/protocol/PIHandler.java	2013-02-13 16:50:15.177517576 +0000
+++ openjdk/corba/src/share/classes/com/sun/corba/se/spi/protocol/PIHandler.java	2013-02-13 16:50:31.285776492 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2003, 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
@@ -25,6 +25,8 @@
 
 package com.sun.corba.se.spi.protocol;
 
+import java.io.Closeable;
+
 import org.omg.PortableInterceptor.ObjectReferenceTemplate ;
 import org.omg.PortableInterceptor.Interceptor ;
 import org.omg.PortableInterceptor.Current ;
@@ -51,7 +53,7 @@
 /** This interface defines the PI interface that is used to interface the rest of the
  * ORB to the PI implementation.
  */
-public interface PIHandler {
+public interface PIHandler extends Closeable {
     /** Complete the initialization of the PIHandler.  This will execute the methods
     * on the ORBInitializers, if any are defined.  This must be done here so that
     * the ORB can obtain the PIHandler BEFORE the ORBInitializers run, since they
diff -Nru openjdk.orig/corba/src/share/classes/com/sun/corba/se/spi/protocol/RequestDispatcherRegistry.java openjdk/corba/src/share/classes/com/sun/corba/se/spi/protocol/RequestDispatcherRegistry.java
--- openjdk.orig/corba/src/share/classes/com/sun/corba/se/spi/protocol/RequestDispatcherRegistry.java	2012-10-26 19:21:49.000000000 +0100
+++ openjdk/corba/src/share/classes/com/sun/corba/se/spi/protocol/RequestDispatcherRegistry.java	2013-02-13 16:50:31.285776492 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2003, 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,33 +37,59 @@
  * This is a registry of all subcontract ID dependent objects.  This includes:
  * LocalClientRequestDispatcherFactory, ClientRequestDispatcher, ServerRequestDispatcher, and
  * ObjectAdapterFactory.
- * XXX Should the registerXXX methods take an scid or not?  I think we
- * want to do this so that the same instance can be shared across multiple
- * scids (and this is already true for ObjectAdapterFactory and LocalClientRequestDispatcherFactory),
- * but this will require some changes for ClientRequestDispatcher and ServerRequestDispatcher.
  */
 public interface RequestDispatcherRegistry {
-    // XXX needs javadocs!
 
+    /** Register a ClientRequestDispatcher for a particular subcontract ID.
+     * The subcontract ID appears in the ObjectKey of an object reference, and is used
+     * to control how a remote method invocation is processed by the ORB for a
+     * particular kind of object reference.
+     */
     void registerClientRequestDispatcher( ClientRequestDispatcher csc, int scid) ;
 
+    /** Get the ClientRequestDispatcher for subcontract ID scid.
+     */
     ClientRequestDispatcher getClientRequestDispatcher( int scid ) ;
 
+    /** Register a LocalClientRequestDispatcher for a particular subcontract ID.
+     * The subcontract ID appears in the ObjectKey of an object reference, and is used
+     * to control how a particular kind of colocated request is processed.
+     */
     void registerLocalClientRequestDispatcherFactory( LocalClientRequestDispatcherFactory csc, int scid) ;
 
+    /** Get the LocalClientRequestDispatcher for subcontract ID scid.
+     */
     LocalClientRequestDispatcherFactory getLocalClientRequestDispatcherFactory( int scid ) ;
 
+    /** Register a CorbaServerRequestDispatcher for a particular subcontract ID.
+     * The subcontract ID appears in the ObjectKey of an object reference, and is used
+     * to control how a particular kind of request is processed when received by the ORB.
+     */
     void registerServerRequestDispatcher( CorbaServerRequestDispatcher ssc, int scid) ;
 
+    /** Get the CorbaServerRequestDispatcher for subcontract ID scid.
+     */
     CorbaServerRequestDispatcher getServerRequestDispatcher(int scid) ;
 
+    /** Register a CorbaServerRequestDispatcher for handling an explicit object key name.
+     * This is used for non-standard invocations such as INS and the bootstrap name service.
+     */
     void registerServerRequestDispatcher( CorbaServerRequestDispatcher ssc, String name ) ;
 
+    /** Get the CorbaServerRequestDispatcher for a particular object key.
+     */
     CorbaServerRequestDispatcher getServerRequestDispatcher( String name ) ;
 
+    /** Register an ObjectAdapterFactory for a particular subcontract ID.
+     * This controls how Object references are created and managed.
+     */
     void registerObjectAdapterFactory( ObjectAdapterFactory oaf, int scid) ;
 
+    /** Get the ObjectAdapterFactory for a particular subcontract ID scid.
+     */
     ObjectAdapterFactory getObjectAdapterFactory( int scid ) ;
 
-    Set getObjectAdapterFactories() ;
+    /** Return the set of all ObjectAdapterFactory instances that are registered.
+     */
+    Set<ObjectAdapterFactory> getObjectAdapterFactories();
 }
