Bob Balaban's Blog

     
    alt

    Bob Balaban

     

    Geek-o-Terica 7: Garbage, threads and the CORBA classes in Notes

    Bob Balaban  May 23 2009 11:15:00 AM
    Greetings, Geeks!

    I actually thought that my previous Geek-o-Terica post on garbage collection (gc) and java and Notes and threads would be the final one on that topic. For one thing, there's only so much you can say about it without falling asleep.

    However, I had a couple of requests to map that discussion onto the "other" Java APIs for Notes, the so-called CORBA classes. It's a good point, so here we go.

    First, a brief review of what's different about the CORBA classes. They're different from the "regular" back-end classes for Notes in that they constitute a Java library (NCSO.jar) that does not need a locally installed Notes Client or Domino Server in order to operate. They work remotely with any Domino server that runs the DIIOP server task. The CORBA classes (so named because the remoting technology they use is based on the Object Management Group's "Common Object Request Broker Architecture" specification).

    The classes in NCSO.jar implement the exact same Java interfaces (Session, Database, View, Document, etc etc) that the "local" classes in Notes.jar do, so you (with a few very minor exceptions) use them the same way. But the implementation is entirely different. When you invoke a method on a "local" object instance, a piece of Java wrapper code calls into the C++ code in Notes/Domino that implements the back-end classes (lsxbe). The C++ code uses the Notes C API, and things rock on.

    The job of the "remote" Java classes is entirely different. Each object instance in NCSO.jar is really just a proxy object: it's job is to assemble the input parameters into a command buffer, format it according to the CORBA wire-protocol specification (IIOP, thus the name DIIOP for the server task), and ship it to the server. Each CORBA proxy object is bound to a "real" back-end object on the server, which is the thing that does the real work.

    This architecture has a number of different implications on how you code your CORBA-based Java app:

       1) You still have to use recycle(). Not so much to protect the memory heap of your local JVM (because there are no "real" back-end classes to de-allocate there), but to recover lsxbe/C++ memory on the server.
       
       2) There's no (discernable) connection between threads you may generate on your client machine and threads within the DIIOP server task. Since your program is not directly using the CAPI, your CORBA program is not bound by any of the threading rules you have when running on a Notes/Domino machine using the local classes. You can freely use CORBA objects across threads, no init/term required.

       3) You can actually connect to multiple servers using the CORBA classes. You'd do that by creating one Session instance for each server. But you can NOT mix and match child objects across servers, that dog just won't hunt.

    Hope this helps. (Hope this is enough )

    Geek ya later!

    (Need expert application development architecture/coding help? Contact me at: bbalaban, gmail.com)
    Follow me on Twitter @LooseleafLLC
    This article ┬ęCopyright 2009 by Looseleaf Software LLC, all rights reserved. You may link to this page, but may not copy without prior approval.
    Comments

    1Daniele Vistalli  5/23/2009 12:45:09 PM  Geek-o-Terica 7: Garbage, threads and the CORBA classes in Notes

    Thanks for the deep dive in the CORBA space, this confirms what I learned over time. Very appreciated.

    2Simon O’Doherty  5/25/2009 5:39:41 AM  Geek-o-Terica 7: Garbage, threads and the CORBA classes in Notes

    To add to that if you get a NotesException thrown then you should always err on the side of caution that the related objects are no longer valid and should be recycled.

    For example if you get a "server not responding" error there is no guarantee that your back end data is still there when the connection comes back.

    3Mark Dixon  5/27/2009 10:39:24 AM  Enough is never enough :-)

    Thanks for all the info, it helps to know how this works under the hood. If you can bear the topic just a little longer, I'd appreciate any insight you have into 'the recycle problem'. I'm absolutely fine with recycle - the whole thread affinity stuff and all that - until you get to the paragraph in the docs that says

    If you create more than one object to represent the same Domino element, recycling one recycles all. For example:

    View v1 = db.getView("All");

    View v2 = db.getView("All");

    v1.recycle(); // also recycles v2

    Now recycle is totally unusable. For example, if I'm writing a helper method that calls db.getView(), should I recycle the resulting View object? Even in a single-threaded program, I can't unless I know that none of the methods currently on the call stack have that view open. So short of building Andrew's global check in/check out engine for keeping track of what Domino elements are in use, I can never safely call recycle unless I know the entire global state of my program.

    If the doc is correct then I'm having a hard time working out how recycle is intended to be used. Is it really true that if I end up opening two completely separate java objects that just happen to correspond to the same note or database then recycling one recycles both? If it is then the classic example of recycling in a loop is buggy because it can invalidate documents that the current method or any of its callers may have open before the loop. It makes perfect sense that if I copy objects around then recycling one will recycle all copies, but two independently-created objects corresponding to the same note or database can't recycle together or the API is unusable.

    As described in the doc, I just can't come up with a sensible way to use recycle and any guidance is much appreciated!

    Thanks

    Mark

    4Bob Balaban  5/28/2009 6:13:36 PM  Geek-o-Terica 7: Garbage, threads and the CORBA classes in Notes

    @2 - Simon, I agree. Thanks for pointing that out.

    @3 - Here's the short explanation: The whole back-end classes subsystem tries to be parsimonious with objects; it keeps track of everything

    it creates, and instead of creating a duplicate object (2 Database objects that represent the same NSF, for example), it finds the one that

    already exists and gives you that one.

    So, if you create 2 Session objects, they both point to the same underlying Session C++ object. Same with Session.getDatabase() calls,

    Notes will try to find an existing object that represents that db and return that one, rather than creating a new one.

    When a back-end Java object gets recycled, Notes (lsxbe, actually) has a way to tell the JVM that the object has been invalidated. So

    if you have 2, as in your example, and destroy 1, the other reference in the other variable is automatically invalidated.

    It's unfortunate (for many reasons) that the whole recycle() thing was necessary. The simplest explanation of why is that, in the end,

    it's only the application that can know for sure when it's really done with an object.

    If you can't find a way to keep track within your app of when you're really done with an object, it's a problem, potentially. Refcounting is

    one (tedious) way, there are others. Assigning a single thread to a single database is another scheme that i have had luck with. Somehow

    you either have to keep track, or trust that you won't run out of memory before you get to recycle the Session.