Sparx Systems Forum

Enterprise Architect => Automation Interface, Add-Ins and Tools => Topic started by: chrvi on May 21, 2007, 02:09:13 am

Title: How to free memory consumed by EA while iterating?
Post by: chrvi on May 21, 2007, 02:09:13 am
Hi,

I've got a large project tree in EA.
I need to process (via automation (from Java)) all the tree data so I recursively process subcollections of a parent object (packages in a package, elements in a package or element, mehods in a element etc.).

When I process all the objects in a subcollection and return to the parental level I need to free memory which has been consumed by e.g. GetAt method calls while processing the subcollection.

Since the project tree I'm working with has several thousand nodes I quickly get out of resources if I don't free the memory consumed by EA after processing a perticular subtree (i.e. collections within a parental object).

Is there a way of destroying the unnecessary created COM objects? (I don't understand COM much so please forgive me the rather confusing words to follow) I guess I just create lots of COM objects through GetAt function calls and while Java garbage collector take care of java objects it has nothing to do with COM objects and I'll have to somehow destroy them explicitly.

I'll be grateful for any advice.

PS: I'm using the EA version 6.5.799 (not the newest) without eaapi.jar and SSJavaCOM.dll. Instead, I'm using JACOB and generated java classes which correspond to EA objects.
The principal of using these techniques should be the same I believe. Or do you think that using the new version with eaapi.jar and SSJavaCOM.dll could help me somehow with the lack of memory problem?
Title: Re: How to free memory consumed by EA while iterat
Post by: Eve on May 21, 2007, 12:57:51 pm
Unfortunately, the problem is the Java garbage collector is not releasing the java objects.  This in turn means that the COM objects can't be released.

You need to force Java to release the objects holding the COM pointers.  If you were using the provided Java wrapper, you could have used the provided convenience function to do that on the Repository object.  (Compact())  However, that won't be an option so you'll need to call System.gc() followed by System.runFinalization().
Title: Re: How to free memory consumed by EA while iterat
Post by: mikewhit on May 21, 2007, 10:42:10 pm
Surely Java will only hold on to referenced objects.

If there's no reference, the object should be GC-able - unless there's some kind of 'hidden' reference that needs to be deleted explicitly ?
Title: Re: How to free memory consumed by EA while iterat
Post by: Eve on May 22, 2007, 01:02:49 pm
The basic problem (as I understand it) is that the actual Java objects are so small, and as a result the amount of memory the Java VM itself is using is so small that the GC doesn't think that it needs to run.

The problem with this is that the Java objects are holding a reference to a COM object that has its own garbage collection system.

So, you need to force the Java GC to finalize the objects no longer referenced.

Unfortunately there isn't much way around this.  Unless there is some way to tell the Java GC to put a higher priority on some classes that I haven't found.

(Note. What I have said holds true for the Java interface provided by EA, I don't know anything about JACOB but it sounds like it works the same way.)
Title: Re: How to free memory consumed by EA while iterat
Post by: mikewhit on May 23, 2007, 01:34:13 am
Anything useful in java.lang.ref ?

I used that a few years ago - there's an old example here:
http://www.javaworld.com/javaworld/javatips/jw-javatip79.html

When the COM object refcount becomes zero ...
Title: Re: How to free memory consumed by EA while iterat
Post by: chrvi on May 31, 2007, 03:35:02 am
I've just installed the new Enterprise Architect (6.5.805)and started using the eaapi.jar and SSJavaCOM.dll files.

I have a package and I wish to add subpackages as follows:

Collection<Package> subPackages;
subPackages = myPackage.GetPackages();
for (...) {
 newPackage = subPackages.AddNew("Package Name","foo");
    // by the way - what is the second parameter good for?
 newPackage.Update();
 subPackages.Refresh();
}

Now I'm going to process another package and add subpackeges to it in the same way, so I'd like to destroy the existing subPackages COM object since I won't need it any more (EA project has already been updated with the inserted subPackages in the for cycle above) and free the consumed memory.
I tried this:

subPackages.destroy();
subPackages = null;
repository.Compact();

The subPackages COM object was probably destroyed succsessfully, its number set to 0, then I set subpackages to null and called repository.Compact() but the memory usage didn't change at all.
I'm quite desperate 'cause my large model will consume all the memory resources unless I find out how to explicitely free memory at desired places in my code.