lifetime of UNO objects, writing Java exception-safe code
Lionel Elie Mamane
lionel at mamane.lu
Sun Sep 15 07:23:10 PDT 2013
On Fri, Sep 13, 2013 at 02:28:35PM +0200, Stephan Bergmann wrote:
> On 09/13/2013 11:07 AM, Lionel Elie Mamane wrote:
>> On Wed, Sep 11, 2013 at 12:35:15PM +0200, Stephan Bergmann wrote:
>>> First, note that we don't have reference-counting garbage collection
>>> in general in UNO. For example, Java-UNO doesn't use
>>> reference-counting.
>>> Second, note that there needs to be code (the "owner" in the jargon
>>> of the udkapi/com/sun/star/lang/XComponent.idl documentation) that
>>> explicitly calls dispose on a UNO object. It is not magically
>>> called when a UNO object becomes unreachable.
>> So let's take the concrete example of
>> reportbuilder/java/org/libreoffice/report/SDBCReportDataFactory.java
>> around line 233:
>> private String getOrderStatement(final int commandType, final String command, final List sortExpressions)
>> Concretely, the Java code does:
>> final XComponent[] hold = new XComponent[1];
>> final XNameAccess columns = getFieldsByCommandDescriptor(commandType, command, hold);
>> I assume this whole rigmarole with "hold" is to ensure that
>> "dispose()" is called on "columns", providing an owner for it.
>> (I assume it uses this round-about way instead of just declaring the
>> caller the owner of columns because in some conditions columns will be
>> a temporary and in other conditions, it will not; with this setup,
>> this is testable with (hold[0] == null)).
> (At least the documentation you cite above does not make it look
> like keepFieldsAlive could return a null reference.)
In my quote of the documentation, I simplified this point away. It
depends. Sometimes it returns a temporary object (owned by
another temporary that is put in keepFieldsAlive) and sometimes it
returns a long-lived "shared" object that the caller should *not*
dispose.
>> So I need to do something like:
>> final XComponent[] hold = new XComponent[1];
>> try
>> {
>> (...)
>> final XNameAccess columns = getFieldsByCommandDescriptor(commandType, command, hold);
>> (...)
>> if(hold[0] != null)
>> hold[0].dispose();
>> }
>> catch (SQLException ex)
>> {
>> if(hold[0] != null)
>> hold[0].dispose();
>> LOGGER.error("ReportProcessing failed", ex);
>> }
>> catch(java.lang.Exception e)
>> {
>> if(hold[0] != null)
>> hold.dispose();
>> throw e;
>> }
> Why not use a finally block?
Because my knowledge of Java is limited to what I had to
learn. finally blocks seem to be *exactly* what is needed
indeed. Thanks for the pointer.
>> Did I understand what you were saying correctly? This function (and
>> _any_ code getting a fresh/temporary UNO object) needs to clean up
>> after itself manually in this pedestrian, error-prone way? Do we get a
>> cop-out in C++ because of the use of com::sun::star::uno::Reference
>> which calls _pInterface->release()? Do we get a cop-out in any other
>> UNO language? (Python? Basic?)
> This specific Java code obtaining ownership of an XComponent is
> supposed to follow the protocol of XComponent and ensure that
> dispose is called, yes. But not every UNO object implements the
> XComponent protocol, so there is lots of code obtaining references
> to UNO objects that does not need to do this sort of clean-up.
So basically, the documentation of the API call should tell you
whether you have to do that or not. OK.
--
Lionel
More information about the LibreOffice
mailing list