Skip to main content

[JAVA3D-INTEREST] J3D Memory problems

17 replies [Last post]
Anonymous

Hi all.

I've been playing with this problem for a few days, I first discovered it
in 1.3.1, but its still occurring in 1.3.2 build4.

After some memory profiling, the best I can come up with is that the
retained scene graph belonging to the SimpleUniverse for a removed
BranchGroup never gets "cleaned up" properly.
This is something of a problem when there is a high turnover in BranchGroup
objects in the live graph. In the case where I discovered it, this problem
was seriously exacerbated by the fact that the added and removed graphs
contained a very large number of images (something not unlike loading new
levels during a game).

I've cut and pasted a stack from Borland's Optimizeit after OOME occurs
illustrating an ImageComponent which should really be removed since it only
belongs to a node which was explicitly removed before adding any new nodes
(its a test image 512x512, all black):

[] byte[786432]=[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,...]
[] data of java.awt.image.DataBufferByte java.awt.image.DataBufferByte@16126ef
[] dataBuffer of sun.awt.image.ByteInterleavedRaster ByteInterleavedRaster:
width = 512 height = 512 #numDataElements 3 dataOff[0] = 2
[] raster of java.awt.image.BufferedImage BufferedImage@24460d: type = 5
ColorModel: #pixelBits = 24 numComponents = 3 color space =
java.awt.color.IC...
[] element of Object[] 0x1558e968
[] bImage of javax.media.j3d.ImageComponent2DRetained
javax.media.j3d.ImageComponent2DRetained@1712193
[] element of Object[] 0x1558e748
[] element of Object[] 0x1558e738
[] images of javax.media.j3d.Texture2DRetained
javax.media.j3d.Texture2DRetained@14f6e3f
[] texture of javax.media.j3d.AppearanceRetained
javax.media.j3d.AppearanceRetained@1ac3fc7
[] appearance of javax.media.j3d.Shape3DRetained
javax.media.j3d.Shape3DRetained@1bd07dd
[] retained of javax.media.j3d.Shape3D javax.media.j3d.Shape3D@1b0d33c
[] source of javax.media.j3d.Shape3DRetained
javax.media.j3d.Shape3DRetained@dbd4b8
[] element of Object[] 0x1563b6e0
[] elementData of java.util.ArrayList [javax.media.j3d.Shape3DRetained@dbd4b8]
[] users of javax.media.j3d.TextureAttributesRetained
javax.media.j3d.TextureAttributesRetained@521dc
[] textureAttributes of javax.media.j3d.AppearanceRetained
javax.media.j3d.AppearanceRetained@1ac3fc7
[] app of javax.media.j3d.RenderAtom javax.media.j3d.RenderAtom@1d41be6
[] element of Object[] 0x18057440
[] renderAtoms of javax.media.j3d.GeometryAtom
javax.media.j3d.GeometryAtom@145cfef
[] element of Object[] 0x17de1d60
[] element of Object[] 0x17de1d38
[] targetArr of javax.media.j3d.CachedTargets
javax.media.j3d.CachedTargets@1354543
[] element of Object[] 0x17de10f8
[] cachedTargets of javax.media.j3d.TransformGroupRetained
javax.media.j3d.TransformGroupRetained@5e1ea8
[] parentTransformLink of javax.media.j3d.Shape3DRetained
javax.media.j3d.Shape3DRetained@18f48a1
[] retained of javax.media.j3d.Shape3D javax.media.j3d.Shape3D@796e1c
[] source of javax.media.j3d.Shape3DRetained
javax.media.j3d.Shape3DRetained@1317890
[] element of Object[] 0x157a8f90
[] elementData of java.util.ArrayList [javax.media.j3d.Shape3DRetained@1317890]
[] users of javax.media.j3d.TextureAttributesRetained
javax.media.j3d.TextureAttributesRetained@d92090
[] textureAttributes of javax.media.j3d.AppearanceRetained
javax.media.j3d.AppearanceRetained@1ac3fc7
[] retained of javax.media.j3d.Appearance javax.media.j3d.Appearance@d8860e
[] source of javax.media.j3d.AppearanceRetained
javax.media.j3d.AppearanceRetained@1ac3fc7
[] app of javax.media.j3d.RenderAtom javax.media.j3d.RenderAtom@1309271
[] element of Object[] 0x18057068
[] renderAtoms of javax.media.j3d.GeometryAtom
javax.media.j3d.GeometryAtom@e83d2d
[] leafIF of javax.media.j3d.BHLeafNode javax.media.j3d.BHLeafNode@77bc40
[] element of Object[] 0x17ed0ad0
[] bhNodeArr of javax.media.j3d.GeometryStructure
javax.media.j3d.GeometryStructure@1e2dee9
[] geometryStructure of com.sun.j3d.utils.universe.SimpleUniverse
com.sun.j3d.utils.universe.SimpleUniverse@20ede7

Is there anything I can do to force a flush of retained objects after I
call branchGraph.remove()
*or*
is this a full-blown j3d memory leak I just need to get used to?

Best,
Matt

---------------------------------------------------------------------
To unsubscribe, e-mail: interest-unsubscribe@java3d.dev.java.net
For additional commands, e-mail: interest-help@java3d.dev.java.net

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
jada
Offline
Joined: 2004-03-17

That's great to know. Thanks for the feedback.

- Chien.

jada
Offline
Joined: 2004-03-17

Vaidya,
I thought I did followed up with you on your test program. :-) If I remember correctly, the OOM problem in
your test program, is caused by the apps. doing add/remove of geometries in a faster rate than the frame rate can cope. Such situation will cause a backlog in messages send to Java 3D, and it will eventually lead to OOM.
Please send us your test program, if this isn't the case.

thanks,

- Chien.

nvaidya
Offline
Joined: 2004-08-03

> Vaidya,
> I thought I did followed up with you on your test
> est program. :-) If I remember correctly, the OOM
> problem in
> your test program, is caused by the apps. doing
> add/remove of geometries in a faster rate than the
> frame rate can cope. Such situation will cause a
> backlog in messages send to Java 3D, and it will
> eventually lead to OOM.
> Please send us your test program, if this isn't
> n't the case.
>
> thanks,
>
> - Chien.

Oh No ! Not again, Chien :). This is the second time you're misquoting me and I hope it is not deliberate. Here is the text of one of my e-mails to you around February 25, 2004.

[begin quote]
Vaidya's e-mail to Chien-----------------------------
Hi Chien,

Much appreciate your taking time to respond.

OK ! The objective of my testcase is not to run Java3D
attach/detach sequences at very small intervals - I do understand
that 50ms or lower sounds a little ridiculous. But the objective is
to find out if there is a memory leak of some kind which causes an
OOM error. In my actual application I can reproduce this error quite
systematically. In the small testcase that I sent first, version 1
with IndexedTriangleArray with ByRef, you had also seen the problem I
think at 200ms or so. In the case of the sphere problem which you
designed, and which is not ByRef, I had to keep small time intervals
to mimic that kind of OOM problem. In the process, I may have tripped
on the Java3D frame rate limitation; BUT, that is a different subject
altogether and not related to the original problem, as described
above, that I'm trying to troubleshoot.

The question is are you going to be busy till the end of GDC
2004 ? Or, is it possible that you may have time before then ? I need
only theoretical guidance on the internals of Java3D with respect to
JNI memory leaks if any.

The issue simply is Java3D throws OOM error when garbage is in a
not-yet-collected state and when there is sufficient heap memory
still available. Sometimes, it panics and gives OOM error, but
manages to recover and run a Full GC and reclaim memory. THIS IS
really weird and I would appreciate if you know anything about this
behavior, PLEASE !

Thanks and Best Regards

Vaidya

[End Quote]----------------------------------------

The point was that I was trying to demonstrate unusual Java3D behavior with respect to reclaiming memory and consequently unexpected OOM errors sometimes. On my config. I could most certainly observe them. It is possible, I admit, that the testcases I had cooked up may or may not have illustrated the problems that I was struggling with in my actual application. Now, I repeat, one of the testcases that I had sent also had a nice GUI (with a memory monitor) to demonstrate memory retention with respect to BG detach. That issue wasn't common knowledge then as is evidenced by the flurry of e-mails in the Java3D-interest forums recently with Mike Pilone in particular asking around for a suitable testcase. And I was hesitant to offer a testcase because I didn't want to open up a Pandora's box again :).

I think one of the reasons that my memory calculations were a little awry in February was possibly because I was also fighting at that time the leak due to Java3D allocating memory redundantly for index arrays when the UCIO flag is set - Issue #23.

I believe Scott Hong has a point that it is also necessary to do removeAllChildren() during a detach. I've noticed some benefit in that too, and now do that as a matter of habit.

In summary, I think resolving Issue #9 may be a possible solution to some of the issues that I had seen long back. I'll simply choose to wait until then because my current priority is to finish some of my stuff on dynamic OffScreenCanvas3D. (BTW, if you need any kind of testing with Pbuffers, I'll be happy to assist. I have some nice apps. that I could use to benchmark.)

jada
Offline
Joined: 2004-03-17

Vaidya,
Oh yes, now that I remembered, I did run OptimizeIt
on your test program but didn't see any memory leak
reported at that time. I believe, as you have noted,
issue 23 might caused the confusion at that time. (Thanks
for stepping up to fix issue 23. We greatly appreciate
your effort. :-))

BTW, we've just completed a couple of fixes to offScreen
related bugs. Here is the log from my putback :
Issue number: 4, 28, 71 and 76
Windows OpenGL only : This fix will use hardware Pbuffer for offScreenBuffer rendering if the graphics hardware support it, else BitMap is use as a fallback.

1) Fixed issue 4 - Speed of OffScreen Canvas3D
2) Fixed issue 28 - Combine Mode & Missing Texture in OffScreen snapshot on Win/XP
3) Fixed issue 71 - OGL: OffScreen canvas ignore GraphicsConfigTemplate under windows.
4) Fixed issue 76 - OffScreen rendering should use Pbuffer on Windows / OpenGL
5) Cleanup native ChoosePixelFormat code.

Please check it out and test it.

thanks,
Chien.

nvaidya
Offline
Joined: 2004-08-03

> Vaidya,
> Oh yes, now that I remembered, I did run
> run OptimizeIt
> on your test program but didn't see any memory leak
> reported at that time. I believe, as you have noted,
>
> issue 23 might caused the confusion at that time.
> (Thanks
> for stepping up to fix issue 23. We greatly
> appreciate
> your effort. :-))

The pleasure was truly mine. I hope Marty Vona (Maestro application) and others get to try the fix to gauge the benefits.

>
> BTW, we've just completed a couple of fixes to
> offScreen
> related bugs. Here is the log from my putback :
> Issue number: 4, 28, 71 and 76
> Windows OpenGL only : This fix will use hardware
> e Pbuffer for offScreenBuffer rendering if the
> graphics hardware support it, else BitMap is use as a
> fallback.
>
> 1) Fixed issue 4 - Speed of OffScreen Canvas3D
> 2) Fixed issue 28 - Combine Mode & Missing Texture
> e in OffScreen snapshot on Win/XP
> 3) Fixed issue 71 - OGL: OffScreen canvas ignore
> e GraphicsConfigTemplate under windows.
> 4) Fixed issue 76 - OffScreen rendering should use
> e Pbuffer on Windows / OpenGL
> 5) Cleanup native ChoosePixelFormat code.
>
> Please check it out and test it.
>

Yes, I checked out the new version and it compiled without a hitch. HeHe ! Great work on the pbuffer support. My app. ran straight off without any visual glitches (square dimensioned snapshots) and the speedups - simply great. I put in some additional printouts to verify that pbuffer support was indeed getting triggered. So with Issues 28 and 76 fixed, I can now do in real time and on a per frame basis, screen capture into a texture, blending with existing geometry using multitexture combine interpolate mode, and respecify view-dependent texture coordinates in ByRef+UCIO mode. The missing specular highlights discovered by Kevin also seem to have been fixed. Great show !

Thanks,

Vaidya

mikofclassx
Offline
Joined: 2003-07-02

The PBuffer support is really great. I can have hardware FSAA and great speedups. Great job on a much needed feature.

The next days I'll start my work on the transparent background feature.

Mik
--

mikofclassx
Offline
Joined: 2003-07-02

UPDATE:

ok, I did it. It was just a quick fix on chooseSTDPixelFormat() plus some other little things. It works very well.

Anyway I don't know if the fix is really ok until I do some additional tests.

Cheers,

Mik
--

jada
Offline
Joined: 2004-03-17

Mik,
We will look into it, if you can send us your suggested changes.

Thanks,
Chien.

Matthew Hilliard

I have no idea if this is the same problem or not, but one of the key
features of this leak is it isn't constrained to removing BranchGroups, it
actually occurs when Locales are removed as well (this was in a private
email to kcr, after I lost access to the problem on the boards).

Matt

---------------------------------------------------------------------
To unsubscribe, e-mail: interest-unsubscribe@java3d.dev.java.net
For additional commands, e-mail: interest-help@java3d.dev.java.net

Philippe pelzman

Thank you for your response, Matt.
It's very kind of you. I'll try to survive this bug !

Philippe

-----Message d'origine-----
De : Matthew Hilliard [mailto:matt@beq.ca]
Envoyé : mercredi 13 octobre 2004 18:12
À : interest@java3d.dev.java.net
Objet : Re: [JAVA3D-INTEREST] J3D Memory problems

Hi Phillipe.
I'm sorry to say we still run out of memory, and we have no decent
work-around aside from hoping we catch the OOME on the correct thread
(we
have a high probability of catching it on the thread that adds new
content
to the live graph) and respawning the entire Java process before
exiting.
Another proposed but untested fix we were going to investigate was to
explicitly replace the Canvas3d (after calling stopRenderer() on it) and

the SimpleUniverse (here we would need to drop VirtualUniverse so we can

call SimpleUniverse's cleanup() first) and simply recreate the j3d
infrastructure rather than the entire Java process. If it works, it
should
be substantially faster to get a process back on its feet. You could
also
time it to occur proactively rather than reactively (before all scene
swaps, for exapmle). If it doesn't work, it might help profile the
problem
in terms of "where exactly is the memory going?"
We also did find that increasing the heap size (to -Xmx390), could delay

the problem, which in a few isolated cases was good enough--although if
we
increased it too much, the performance would significantly degrade as
memory began to swap more (fps would drop to about 10-20% of normal).

Finally, if you have a simple example that causes this problem, I'm sure

Kevin would like to see it.

Best,
Matt

At 07:00 AM 10/13/2004, you wrote:
>Hi Matt
>
>I struggle with the same problem as yours.
>Could you find a solution ?
>
>thank you in advance
>
>Philippe
>---
>[Message sent by forum member 'ppelzman' (Philippe Pelzman)]
>
>http://www.javadesktop.org/forums/thread.jspa?messageID=33115腛
>
>---------------------------------------------------------------------
>To unsubscribe, e-mail: interest-unsubscribe@java3d.dev.java.net
>For additional commands, e-mail: interest-help@java3d.dev.java.net

---------------------------------------------------------------------
To unsubscribe, e-mail: interest-unsubscribe@java3d.dev.java.net
For additional commands, e-mail: interest-help@java3d.dev.java.net

---------------------------------------------------------------------
To unsubscribe, e-mail: interest-unsubscribe@java3d.dev.java.net
For additional commands, e-mail: interest-help@java3d.dev.java.net

scotthong
Offline
Joined: 2006-05-05

Hi,

I've struggled with the same problem before fighting with same memory leak issue.

The solutions:
You must dive deep into the SG that hold reference to other objects. Clean up everything including the object referenced by setUserData. Make sure that any reference to the SG get cleaned up as well. Detaching the parent BG is not enough to get the whole SG garbage collected. There might be some references to the SG objects that prevent the whole SG from been garbage collected. This will result in long delay (application pause) when a huge SG is been cleaned up. (Detaching a Group object doesn't remove the children that a Group object holds, you might want to call removeAllChildren and all the child Group node's removeAllChildren.)

I've used a test program to stress test possible memory leaks. The program basically goes though thousands of data models as large as 300Mb, loading and displaying the models and then trash the view. The memory usage goes up as high as 1Gb. The memory usage always comes down to the same reasonable level (in my case ~168Mb). The longest time I kept the stress test program running for a week without any problem.

You might want to adopt a similiar strategy to create a stress test program that repeatly loads your data using your data model, display the resulting SG and then trash the view (SG deep cleanning) as well as cleaning up all the references that your data model might hold. This should take care of the memory leak business. This might force you to come up with a similiar "Destructor" function for each class that is similiar to C++ to clean up each object.

The memory leak might be Java3D specific but this is worth a try. Java seems to trick us to think that Garbage Collection magically makes the memory leak problem go away without paying attention to de-reference all the objects that are not been used anymore.

-- Scott

Mike Pilone

This problem may be related to issue 9. I have had two different sources of
OOM exceptions in my application due to the use of finalizers in J3D.

It appears that rapidly changing image components or geometry (I believe I
was using TriangleStripArrays) can cause an OOM if the finalizer doesn't run
fast enough (and the JVM does not guarantee that it will ever run). The data
structures get put in the finalizer list and sit there forever taking up
valuable resources.

I found a few work arounds that are not too pretty, but they got me by. I
suggest that the people seeing OOM problems profile their code to find the
problem. An application like JProfiler should give you an answer quickly.
Once you have the answer, WRITE A TEST CASE! The Java3D team is somewhat
limited in personnel and they have a lot on their plate. Do not expect them
to fix a bug if no one can reproduce it.

-mike

-----Original Message-----
From: java3d-interest@javadesktop.org
[mailto:java3d-interest@javadesktop.org]
Sent: Friday, October 15, 2004 1:09 AM
To: interest@java3d.dev.java.net
Subject: Re: [JAVA3D-INTEREST] J3D Memory problems

Hi,

I've struggled with the same problem before fighting with same memory leak
issue.

The solutions:
You must dive deep into the SG that hold reference to other objects. Clean
up everything including the object referenced by setUserData. Make sure that
any reference to the SG get cleaned up as well. Detaching the parent BG is
not enough to get the whole SG garbage collected. There might be some
references to the SG objects that prevent the whole SG from been garbage
collected. This will result in long delay (application pause) when a huge SG
is been cleaned up. (Detaching a Group object doesn't remove the children
that a Group object holds, you might want to call removeAllChildren and all
the child Group node's removeAllChildren.)

I've used a test program to stress test possible memory leaks. The program
basically goes though thousands of data models as large as 300Mb, loading
and displaying the models and then trash the view. The memory usage goes up
as high as 1Gb. The memory usage always comes down to the same reasonable
level (in my case ~168Mb). The longest time I kept the stress test program
running for a week without any problem.

You might want to adopt a similiar strategy to create a stress test program
that repeatly loads your data using your data model, display the resulting
SG and then trash the view (SG deep cleanning) as well as cleaning up all
the references that your data model might hold. This should take care of the
memory leak business. This might force you to come up with a similiar
"Destructor" function for each class that is similiar to C++ to clean up
each object.

The memory leak might be Java3D specific but this is worth a try. Java seems
to trick us to think that Garbage Collection magically makes the memory leak
problem go away without paying attention to de-reference all the objects
that are not been used anymore.

-- Scott
---
[Message sent by forum member 'scotthong' (Scott Hong)]

http://www.javadesktop.org/forums/thread.jspa?messageID=33394&#33394

---------------------------------------------------------------------
To unsubscribe, e-mail: interest-unsubscribe@java3d.dev.java.net
For additional commands, e-mail: interest-help@java3d.dev.java.net

---------------------------------------------------------------------
To unsubscribe, e-mail: interest-unsubscribe@java3d.dev.java.net
For additional commands, e-mail: interest-help@java3d.dev.java.net

ppelzman
Offline
Joined: 2004-10-06

Hi Matt

I struggle with the same problem as yours.
Could you find a solution ?

thank you in advance

Philippe

Matthew Hilliard

Hi Phillipe.
I'm sorry to say we still run out of memory, and we have no decent
work-around aside from hoping we catch the OOME on the correct thread (we
have a high probability of catching it on the thread that adds new content
to the live graph) and respawning the entire Java process before exiting.
Another proposed but untested fix we were going to investigate was to
explicitly replace the Canvas3d (after calling stopRenderer() on it) and
the SimpleUniverse (here we would need to drop VirtualUniverse so we can
call SimpleUniverse's cleanup() first) and simply recreate the j3d
infrastructure rather than the entire Java process. If it works, it should
be substantially faster to get a process back on its feet. You could also
time it to occur proactively rather than reactively (before all scene
swaps, for exapmle). If it doesn't work, it might help profile the problem
in terms of "where exactly is the memory going?"
We also did find that increasing the heap size (to -Xmx390), could delay
the problem, which in a few isolated cases was good enough--although if we
increased it too much, the performance would significantly degrade as
memory began to swap more (fps would drop to about 10-20% of normal).

Finally, if you have a simple example that causes this problem, I'm sure
Kevin would like to see it.

Best,
Matt

At 07:00 AM 10/13/2004, you wrote:
>Hi Matt
>
>I struggle with the same problem as yours.
>Could you find a solution ?
>
>thank you in advance
>
>Philippe
>---
>[Message sent by forum member 'ppelzman' (Philippe Pelzman)]
>
>http://www.javadesktop.org/forums/thread.jspa?messageID=33115腛
>
>---------------------------------------------------------------------
>To unsubscribe, e-mail: interest-unsubscribe@java3d.dev.java.net
>For additional commands, e-mail: interest-help@java3d.dev.java.net

---------------------------------------------------------------------
To unsubscribe, e-mail: interest-unsubscribe@java3d.dev.java.net
For additional commands, e-mail: interest-help@java3d.dev.java.net

jada
Offline
Joined: 2004-03-17

Yes, we hope to have a test program for this issue. We would like to have this resolved in the coming Java 3D 1.3.2 release, if we can receive a test program by end of October.

thanks,

- Chien.

nvaidya
Offline
Joined: 2004-08-03

> Yes, we hope to have a test program for this issue.
> We would like to have this resolved in the coming
> Java 3D 1.3.2 release, if we can receive a test
> program by end of October.
>
> thanks,
>
> - Chien.

Chien,
Are you looking for a testcase to progress with this issue ? And is the issue here that Java3D doesn't let go off the memory associated with a BG when the BG is detached ? I had sent a testcase (with a GUI for attach/detach/addDummyBG etc.) to you in February this year which I though will demo *among other things* this kind of issue. Is my understanding correct here or is this a totally different one ? Anyways, I do have somewhere those testcases and I can resubmit one if it would help.

--Vaidya

kcr
Offline
Joined: 2004-03-17

Yes, we are looking for a test case, but not for the issue of holding onto the last BG. That one is fairly well understood, and is documented as Issue 75 (which was transferred from BugTraq bug 4884065). As indicated in the bug report, this isn't a leak in the sense that the next branch group will free the memory used by the previous. Since there is a simple workaround, we don't plan to address this for 1.3.2.

What we are looking for is a test program for Issue 25, which does appear to be a leak where memory is never freed, even when a new branch group has been added.

-- Kevin