Merge
authorlana
Mon, 20 Dec 2010 17:18:56 -0800
changeset 7591 c7ae8ae2340b
parent 7578 670662dc2a25 (current diff)
parent 7590 c4ed8d82b083 (diff)
child 7592 6f2f149fc966
Merge
--- a/corba/src/share/classes/com/sun/corba/se/impl/encoding/BufferManagerWriteStream.java	Sat Dec 18 18:29:58 2010 -0800
+++ b/corba/src/share/classes/com/sun/corba/se/impl/encoding/BufferManagerWriteStream.java	Mon Dec 20 17:18:56 2010 -0800
@@ -30,12 +30,14 @@
 import com.sun.corba.se.impl.protocol.giopmsgheaders.Message;
 import com.sun.corba.se.impl.protocol.giopmsgheaders.MessageBase;
 import com.sun.corba.se.impl.protocol.giopmsgheaders.FragmentMessage;
+import com.sun.corba.se.impl.protocol.giopmsgheaders.ReplyMessage;
 import com.sun.corba.se.impl.encoding.BufferManagerWrite;
 import com.sun.corba.se.impl.encoding.ByteBufferWithInfo;
 import com.sun.corba.se.impl.encoding.CDROutputObject;
 import com.sun.corba.se.spi.orb.ORB;
 import com.sun.corba.se.pept.transport.Connection;
 import com.sun.corba.se.pept.encoding.OutputObject;
+import org.omg.CORBA.SystemException;
 
 /**
  * Streaming buffer manager.
@@ -66,7 +68,13 @@
         // Set the fragment's moreFragments field to true
         MessageBase.setFlag(bbwi.byteBuffer, Message.MORE_FRAGMENTS_BIT);
 
-        sendFragment(false);
+        try {
+           sendFragment(false);
+        } catch(SystemException se){
+                orb.getPIHandler().invokeClientPIEndingPoint(
+                        ReplyMessage.SYSTEM_EXCEPTION, se);
+                throw se;
+        }
 
         // Reuse the old buffer
 
--- a/corba/src/share/classes/com/sun/corba/se/impl/io/ObjectStreamClass.java	Sat Dec 18 18:29:58 2010 -0800
+++ b/corba/src/share/classes/com/sun/corba/se/impl/io/ObjectStreamClass.java	Mon Dec 20 17:18:56 2010 -0800
@@ -85,6 +85,9 @@
 
     private static Hashtable translatedFields;
 
+    /** true if represents enum type */
+    private boolean isEnum;
+
     private static final Bridge bridge =
         (Bridge)AccessController.doPrivileged(
             new PrivilegedAction() {
@@ -359,6 +362,7 @@
         }
 
         name = cl.getName();
+        isEnum = Enum.class.isAssignableFrom(cl);
         superclass = superdesc;
         serializable = serial;
         if (!forProxyClass) {
@@ -401,7 +405,8 @@
         if (!serializable ||
             externalizable ||
             forProxyClass ||
-            name.equals("java.lang.String")) {
+            name.equals("java.lang.String") ||
+            isEnum) {
             fields = NO_FIELDS;
         } else if (serializable) {
             /* Ask for permission to override field access checks.
@@ -502,7 +507,7 @@
          *
          * NonSerializable classes have a serialVerisonUID of 0L.
          */
-         if (isNonSerializable()) {
+         if (isNonSerializable() || isEnum) {
              suid = 0L;
          } else {
              // Lookup special Serializable members using reflection.
--- a/corba/src/share/classes/com/sun/corba/se/impl/oa/poa/AOMEntry.java	Sat Dec 18 18:29:58 2010 -0800
+++ b/corba/src/share/classes/com/sun/corba/se/impl/oa/poa/AOMEntry.java	Mon Dec 20 17:18:56 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2010, 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
@@ -45,6 +45,10 @@
 import com.sun.corba.se.impl.orbutil.concurrent.Mutex ;
 import com.sun.corba.se.impl.orbutil.concurrent.CondVar ;
 
+import org.omg.CORBA.SystemException ;
+
+import org.omg.PortableServer.POAPackage.ObjectAlreadyActive ;
+
 /** AOMEntry represents a Servant or potential Servant in the ActiveObjectMap.
 * It may be in several states to allow for long incarnate or etherealize operations.
 * The methods on this class mostly represent input symbols to the state machine
@@ -121,6 +125,12 @@
         }
     } ;
 
+    private static Action oaaAction = new ActionBase( "throwObjectAlreadyActive" ) {
+         public void doIt( FSM fsm, Input in ) {
+             throw new RuntimeException( new ObjectAlreadyActive() ) ;
+         }
+    } ;
+
     private static Guard waitGuard = new GuardBase( "wait" ) {
         public Guard.Result evaluate( FSM fsm, Input in ) {
             AOMEntry entry = (AOMEntry)fsm ;
@@ -173,19 +183,23 @@
         engine.add( INCARN,  START_ETH, waitGuard,              null,               INCARN      ) ;
         engine.add( INCARN,  INC_DONE,                          null,               VALID       ) ;
         engine.add( INCARN,  INC_FAIL,                          decrementAction,    INVALID     ) ;
+        engine.add( INCARN,  ACTIVATE,                          oaaAction,          INCARN      ) ;
 
         engine.add( VALID,   ENTER,                             incrementAction,    VALID       ) ;
         engine.add( VALID,   EXIT,                              decrementAction,    VALID       ) ;
         engine.add( VALID,   START_ETH, greaterZeroGuard,       null,               ETHP        ) ;
         engine.add( VALID,   START_ETH, zeroGuard,              null,               ETH         ) ;
+        engine.add( VALID,   ACTIVATE,                          oaaAction,          VALID       ) ;
 
         engine.add( ETHP,    ENTER,     waitGuard,              null,               ETHP        ) ;
         engine.add( ETHP,    START_ETH,                         null,               ETHP        ) ;
         engine.add( ETHP,    EXIT,      greaterOneGuard,        decrementAction,    ETHP        ) ;
         engine.add( ETHP,    EXIT,      oneGuard,               decrementAction,    ETH         ) ;
+        engine.add( ETHP,    ACTIVATE,                          oaaAction,          ETHP        ) ;
 
         engine.add( ETH,     START_ETH,                         null,               ETH         ) ;
         engine.add( ETH,     ETH_DONE,                          null,               DESTROYED   ) ;
+        engine.add( ETH,     ACTIVATE,                          oaaAction,          ETH         ) ;
         engine.add( ETH,     ENTER,     waitGuard,              null,               ETH         ) ;
 
         engine.setDefault( DESTROYED, throwIllegalStateExceptionAction, DESTROYED ) ;
@@ -217,7 +231,17 @@
     public void etherealizeComplete() { doIt( ETH_DONE ) ; }
     public void incarnateComplete() { doIt( INC_DONE ) ; }
     public void incarnateFailure() { doIt( INC_FAIL ) ; }
-    public void activateObject() { doIt( ACTIVATE ) ; }
+    public void activateObject() throws ObjectAlreadyActive {
+         try {
+             doIt( ACTIVATE ) ;
+         } catch (RuntimeException exc) {
+             Throwable thr = exc.getCause() ;
+             if (thr instanceof ObjectAlreadyActive)
+                 throw (ObjectAlreadyActive)thr ;
+             else
+                 throw exc ;
+         }
+    }
     public void enter() { doIt( ENTER ) ; }
     public void exit() { doIt( EXIT ) ; }
 }
--- a/corba/src/share/classes/com/sun/corba/se/impl/oa/poa/POAPolicyMediatorBase_R.java	Sat Dec 18 18:29:58 2010 -0800
+++ b/corba/src/share/classes/com/sun/corba/se/impl/oa/poa/POAPolicyMediatorBase_R.java	Mon Dec 20 17:18:56 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2010, 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
@@ -107,13 +107,9 @@
             throw new ServantAlreadyActive();
         ActiveObjectMap.Key key = new ActiveObjectMap.Key( id ) ;
 
-        // Note that this can't happen for system assigned IDs since the
-        // POA never hands out the same ID.  However, we make this redundant
-        // check here to share the code.
-        if (activeObjectMap.containsKey(key))
-            throw new ObjectAlreadyActive() ;
+        AOMEntry entry = activeObjectMap.get( key ) ;
 
-        AOMEntry entry = activeObjectMap.get( key ) ;
+        // Check for an ObjectAlreadyActive error
         entry.activateObject() ;
         activateServant( key, entry, servant ) ;
     }
--- a/corba/src/share/classes/com/sun/corba/se/impl/orb/ORBImpl.java	Sat Dec 18 18:29:58 2010 -0800
+++ b/corba/src/share/classes/com/sun/corba/se/impl/orb/ORBImpl.java	Mon Dec 20 17:18:56 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2010, 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
@@ -245,7 +245,14 @@
     // All access to resolver, localResolver, and urlOperation must be protected using
     // resolverLock.  Do not hold the ORBImpl lock while accessing
     // resolver, or deadlocks may occur.
-    private Object resolverLock ;
+    // Note that we now have separate locks for each resolver type.  This is due
+    // to bug 6980681 and 6238477, which was caused by a deadlock while resolving a
+    // corbaname: URL that contained a reference to the same ORB as the
+    // ORB making the call to string_to_object.  This caused a deadlock between the
+    // client thread holding the single lock for access to the urlOperation,
+    // and the server thread handling the client is_a request waiting on the
+    // same lock to access the localResolver.
+
 
     // Used for resolver_initial_references and list_initial_services
     private Resolver resolver ;
@@ -255,8 +262,14 @@
 
     // Converts strings to object references for resolvers and string_to_object
     private Operation urlOperation ;
+    private final Object urlOperationLock = new java.lang.Object() ;
 
     private CorbaServerRequestDispatcher insNamingDelegate ;
+    // resolverLock must be used for all access to either resolver or
+    // localResolver, since it is possible for the resolver to indirectly
+    // refer to the localResolver.  Also used to protect access to
+    // insNamingDelegate.
+    private final Object resolverLock = new Object() ;
 
     private TaggedComponentFactoryFinder taggedComponentFactoryFinder ;
 
@@ -396,7 +409,6 @@
             }
         };
 
-        resolverLock = new java.lang.Object() ;
 
         requestDispatcherRegistry = new RequestDispatcherRegistryImpl(
             this, ORBConstants.DEFAULT_SCID);
@@ -832,7 +844,7 @@
         if (str == null)
             throw wrapper.nullParam() ;
 
-        synchronized (resolverLock) {
+        synchronized (urlOperationLock) {
             org.omg.CORBA.Object obj = (org.omg.CORBA.Object)op.operate( str ) ;
             return obj ;
         }
@@ -1778,7 +1790,7 @@
      */
     public void setURLOperation( Operation stringToObject )
     {
-        synchronized (resolverLock) {
+        synchronized (urlOperationLock) {
             urlOperation = stringToObject ;
         }
     }
@@ -1788,7 +1800,7 @@
      */
     public Operation getURLOperation()
     {
-        synchronized (resolverLock) {
+        synchronized (urlOperationLock) {
             return urlOperation ;
         }
     }
--- a/corba/src/share/classes/com/sun/corba/se/impl/protocol/CorbaClientRequestDispatcherImpl.java	Sat Dec 18 18:29:58 2010 -0800
+++ b/corba/src/share/classes/com/sun/corba/se/impl/protocol/CorbaClientRequestDispatcherImpl.java	Mon Dec 20 17:18:56 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2010, 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
@@ -122,9 +122,6 @@
     implements
         ClientRequestDispatcher
 {
-    // Used for locking
-    private Object lock = new Object();
-
     public OutputObject beginRequest(Object self, String opName,
                                      boolean isOneWay, ContactInfo contactInfo)
     {
@@ -151,7 +148,8 @@
 
         // This locking is done so that multiple connections are not created
         // for the same endpoint
-        synchronized (lock) {
+        //6929137 - Synchronized on contactInfo to avoid blocking across multiple endpoints
+        synchronized (contactInfo) {
             if (contactInfo.isConnectionBased()) {
                 if (contactInfo.shouldCacheConnection()) {
                     connection = (CorbaConnection)
@@ -256,7 +254,7 @@
         registerWaiter(messageMediator);
 
         // Do connection reclaim now
-        synchronized (lock) {
+        synchronized (contactInfo) {
             if (contactInfo.isConnectionBased()) {
                 if (contactInfo.shouldCacheConnection()) {
                     OutboundConnectionCache connectionCache =
@@ -387,11 +385,15 @@
             boolean retry  =
                 getContactInfoListIterator(orb)
                     .reportException(messageMediator.getContactInfo(), e);
+
+            //Bug 6382377: must not lose exception in PI
+
+            // Must run interceptor end point before retrying.
+            Exception newException =
+                    orb.getPIHandler().invokeClientPIEndingPoint(
+                    ReplyMessage.SYSTEM_EXCEPTION, e);
+
             if (retry) {
-                // Must run interceptor end point before retrying.
-                Exception newException =
-                    orb.getPIHandler().invokeClientPIEndingPoint(
-                        ReplyMessage.SYSTEM_EXCEPTION, e);
                 if (newException == e) {
                     continueOrThrowSystemOrRemarshal(messageMediator,
                                                      new RemarshalException());
@@ -400,6 +402,14 @@
                                                      newException);
                 }
             } else {
+                if (newException instanceof RuntimeException){
+                    throw (RuntimeException)newException;
+                }
+                else if (newException instanceof RemarshalException)
+                {
+                    throw (RemarshalException)newException;
+                }
+
                 // NOTE: Interceptor ending point will run in releaseReply.
                 throw e;
             }
--- a/corba/src/share/classes/com/sun/corba/se/impl/transport/CorbaConnectionCacheBase.java	Sat Dec 18 18:29:58 2010 -0800
+++ b/corba/src/share/classes/com/sun/corba/se/impl/transport/CorbaConnectionCacheBase.java	Mon Dec 20 17:18:56 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2010, 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,6 +34,7 @@
 
 import com.sun.corba.se.spi.logging.CORBALogDomains;
 import com.sun.corba.se.spi.orb.ORB;
+import com.sun.corba.se.spi.transport.CorbaConnection;
 import com.sun.corba.se.spi.transport.CorbaConnectionCache;
 
 import com.sun.corba.se.impl.logging.ORBUtilSystemException;
@@ -87,6 +88,14 @@
         }
     }
 
+    public void close() {
+        synchronized (backingStore()) {
+            for (Object obj : values()) {
+                ((CorbaConnection)obj).closeConnectionResources() ;
+            }
+        }
+    }
+
     public long numberOfIdleConnections()
     {
         long count = 0;
--- a/corba/src/share/classes/com/sun/corba/se/impl/transport/CorbaTransportManagerImpl.java	Sat Dec 18 18:29:58 2010 -0800
+++ b/corba/src/share/classes/com/sun/corba/se/impl/transport/CorbaTransportManagerImpl.java	Mon Dec 20 17:18:56 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2010 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
@@ -38,6 +38,7 @@
 import org.omg.CORBA.CompletionStatus;
 
 import com.sun.corba.se.pept.transport.Acceptor;
+import com.sun.corba.se.pept.transport.ConnectionCache;
 import com.sun.corba.se.pept.transport.ByteBufferPool;
 import com.sun.corba.se.pept.transport.ContactInfo;
 import com.sun.corba.se.pept.transport.InboundConnectionCache;
@@ -49,6 +50,8 @@
 import com.sun.corba.se.spi.orb.ORB;
 import com.sun.corba.se.spi.transport.CorbaAcceptor;
 import com.sun.corba.se.spi.transport.CorbaTransportManager;
+import com.sun.corba.se.pept.transport.Connection;
+import com.sun.corba.se.pept.transport.ConnectionCache;
 
 // REVISIT - impl/poa specific:
 import com.sun.corba.se.impl.oa.poa.Policies;
@@ -182,6 +185,12 @@
             if (orb.transportDebugFlag) {
                 dprint(".close->");
             }
+            for (Object cc : outboundConnectionCaches.values()) {
+                ((ConnectionCache)cc).close() ;
+            }
+            for (Object cc : inboundConnectionCaches.values()) {
+                ((ConnectionCache)cc).close() ;
+            }
             getSelector(0).close();
         } finally {
             if (orb.transportDebugFlag) {
--- a/corba/src/share/classes/com/sun/corba/se/impl/transport/SelectorImpl.java	Sat Dec 18 18:29:58 2010 -0800
+++ b/corba/src/share/classes/com/sun/corba/se/impl/transport/SelectorImpl.java	Mon Dec 20 17:18:56 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2010, 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
@@ -32,6 +32,7 @@
 import java.nio.channels.Selector;
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.Map;
 import java.util.Iterator;
 import java.util.List;
 
@@ -66,7 +67,7 @@
     private List deferredRegistrations;
     private List interestOpsList;
     private HashMap listenerThreads;
-    private HashMap readerThreads;
+    private Map readerThreads;
     private boolean selectorStarted;
     private boolean closed;
     private ORBUtilSystemException wrapper ;
@@ -81,7 +82,7 @@
         deferredRegistrations = new ArrayList();
         interestOpsList = new ArrayList();
         listenerThreads = new HashMap();
-        readerThreads = new HashMap();
+        readerThreads = java.util.Collections.synchronizedMap(new HashMap());
         closed = false;
         wrapper = ORBUtilSystemException.get(orb,CORBALogDomains.RPC_TRANSPORT);
     }
@@ -178,8 +179,13 @@
         }
 
         if (eventHandler.shouldUseSelectThreadToWait()) {
-            SelectionKey selectionKey = eventHandler.getSelectionKey();
-            selectionKey.cancel();
+            SelectionKey selectionKey ;
+            synchronized(deferredRegistrations) {
+                selectionKey = eventHandler.getSelectionKey();
+            }
+            if (selectionKey != null) {
+                selectionKey.cancel();
+            }
             selector.wakeup();
             return;
         }
--- a/corba/src/share/classes/com/sun/corba/se/impl/transport/SocketOrChannelConnectionImpl.java	Sat Dec 18 18:29:58 2010 -0800
+++ b/corba/src/share/classes/com/sun/corba/se/impl/transport/SocketOrChannelConnectionImpl.java	Mon Dec 20 17:18:56 2010 -0800
@@ -811,6 +811,7 @@
                     dprint(".close: " + this, e);
                 }
             }
+            closeConnectionResources();
         } finally {
             if (orb.transportDebugFlag) {
                 dprint(".close<-: " + this);
@@ -818,6 +819,28 @@
         }
     }
 
+    public void closeConnectionResources() {
+           if (orb.transportDebugFlag) {
+               dprint(".closeConnectionResources->: " + this);
+           }
+           Selector selector = orb.getTransportManager().getSelector(0);
+           selector.unregisterForEvent(this);
+           try {
+             if (socketChannel != null)
+              socketChannel.close() ;
+                if (socket != null && !socket.isClosed())
+                socket.close() ;
+           } catch (IOException e) {
+             if (orb.transportDebugFlag) {
+                 dprint( ".closeConnectionResources: " + this, e ) ;
+             }
+           }
+           if (orb.transportDebugFlag) {
+               dprint(".closeConnectionResources<-: " + this);
+           }
+     }
+
+
     public Acceptor getAcceptor()
     {
         return acceptor;
--- a/corba/src/share/classes/com/sun/corba/se/pept/transport/ConnectionCache.java	Sat Dec 18 18:29:58 2010 -0800
+++ b/corba/src/share/classes/com/sun/corba/se/pept/transport/ConnectionCache.java	Mon Dec 20 17:18:56 2010 -0800
@@ -41,6 +41,12 @@
     public long numberOfBusyConnections();
 
     public boolean reclaim();
+
+    /** Close all connections in the connection cache.
+     * This is used as a final cleanup, and will result
+     * in abrupt termination of any pending communications.
+     */
+    public void close();
 }
 
 // End of file.
--- a/corba/src/share/classes/com/sun/corba/se/spi/transport/CorbaConnection.java	Sat Dec 18 18:29:58 2010 -0800
+++ b/corba/src/share/classes/com/sun/corba/se/spi/transport/CorbaConnection.java	Mon Dec 20 17:18:56 2010 -0800
@@ -163,6 +163,10 @@
     // REVISIT - MessageMediator parameter?
     public void serverRequestProcessingBegins();
     public void serverRequestProcessingEnds();
+
+    /** Clean up all connection resources.  Used when shutting down an ORB.
+     */
+    public void closeConnectionResources();
 }
 
 // End of file.
--- a/corba/src/share/classes/com/sun/tools/corba/se/idl/toJavaPortable/Stub.java	Sat Dec 18 18:29:58 2010 -0800
+++ b/corba/src/share/classes/com/sun/tools/corba/se/idl/toJavaPortable/Stub.java	Mon Dec 20 17:18:56 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2002, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2010, 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
@@ -344,17 +344,27 @@
     stream.println ("     String str = s.readUTF ();");
     stream.println ("     String[] args = null;");
     stream.println ("     java.util.Properties props = null;");
-    stream.println ("     org.omg.CORBA.Object obj = org.omg.CORBA.ORB.init (args, props).string_to_object (str);");
+    stream.println ("     org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init (args, props);");
+    stream.println ("   try {");
+    stream.println ("     org.omg.CORBA.Object obj = orb.string_to_object (str);");
     stream.println ("     org.omg.CORBA.portable.Delegate delegate = ((org.omg.CORBA.portable.ObjectImpl) obj)._get_delegate ();");
     stream.println ("     _set_delegate (delegate);");
+    stream.println ("   } finally {");
+    stream.println ("     orb.destroy() ;");
+    stream.println ("   }");
     stream.println ("  }");
     stream.println ();
     stream.println ("  private void writeObject (java.io.ObjectOutputStream s) throws java.io.IOException");
     stream.println ("  {");
     stream.println ("     String[] args = null;");
     stream.println ("     java.util.Properties props = null;");
-    stream.println ("     String str = org.omg.CORBA.ORB.init (args, props).object_to_string (this);");
+    stream.println ("     org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init (args, props);");
+    stream.println ("   try {");
+    stream.println ("     String str = orb.object_to_string (this);");
     stream.println ("     s.writeUTF (str);");
+    stream.println ("   } finally {");
+    stream.println ("     orb.destroy() ;");
+    stream.println ("   }");
     stream.println ("  }");
   }