Skip to main content

0utOfMemoryError -- bug?

13 replies [Last post]
rdlecler
Offline
Joined: 2004-05-17
Points: 0

Hi all,

I am getting an outOfMemoryError and I have been able to reduce it to a small piece of runnable code (see below). I was hoping someone might be able to help as I have been struggling with this the last few days thinking that it was something in my application code.

Simple execute and wait for a few minutes and you will get an outOfMemoryError. Of course I tried to make the heap bigger but it just delays the inevitable for a few more minutes. I have looked at all the usual suspects and I am running out of ideas. Now A) I am doing something wrong, but I can't see it; B) There is a bug somewhere in the Java3D libraries.

Any suggestions? I tried profiling the heap but I was getting strange errors when it tried to hook in using the Eclipse profiler, JProfile, as well as javaw through the command line (?).

Any suggestions what might be causing this? Looking for a solution to this it appears that other people seemed to get this error doing similar kinds of operations and as far as I know, this was never resolved in any of the posts I saw.

(see code below)

Thanks
Rob Leclerc

/*
This code essentially adds and removes branchgroups from the scene where each branchgroup holds a sphere. It adds 125 spheres, then removes, and repeats this operation until error occurs. The only explicit allocation that is being done here is with Vector3f but this SHOULD be getting gced.

SphereObject3D is just a wrapper class so I can access the branchgroup and its transforms.
*/

public class MyFrame extends JFrame{
Canvas3D canvas = new Canvas3D(SimpleUniverse.getPreferredConfiguration());;
SimpleUniverse universe = new SimpleUniverse(canvas);
BranchGroup scene = new BranchGroup();
LinkedList spherePool = new LinkedList();
HashMap locations = new HashMap();

public MyFrame(){

ViewingPlatform vp = universe.getViewingPlatform();
scene.setCapability(BranchGroup.ALLOW_CHILDREN_READ);
scene.setCapability(BranchGroup.ALLOW_CHILDREN_WRITE);
scene.setCapability(BranchGroup.ALLOW_CHILDREN_EXTEND);
scene.compile();

universe.addBranchGraph(scene);
Transform3D viewTransform = new Transform3D();
viewTransform.setTranslation(new Vector3d(0, 0, 30f));
universe.getViewingPlatform().getViewPlatformTransform().setTransform(viewTransform);

getContentPane().setLayout(new GridLayout(1,1));
getContentPane().add(canvas);
setSize(640,480);
setVisible(true);

//create a pool of spheres to add and remove from/to scene
Appearance ap = new Appearance();
for(int i = 0; i < 125; i++)
spherePool.add(new SphereObject3D(0.5f,ap));

runLoop();
}

public void runLoop(){
boolean swap = true;
while(true){
for(float x = 0; x < 5; x++){
for(float y = 0; y < 5; y++){
for(float z = 0; z < 5; z++){
if(swap)
addSphere(new Vector3f(x,y,z));
else
removeSphere(new Vector3f(x,y,z));
}
}
}
swap = !swap;
}
}

public void removeSphere(Vector3f p ){
SphereObject3D po = (SphereObject3D)locations.remove(p);
scene.removeChild(po);
po.detach();
returnSphereObject3D(po);
}

public void addSphere(Vector3f p){
SphereObject3D po = newSphereObject3D(p);
locations.put(p,po);
scene.addChild(po);
}

private SphereObject3D newSphereObject3D(Vector3f position){
SphereObject3D po = (SphereObject3D)spherePool.removeFirst();
po.setPosition(position);
return po;
}

private void returnSphereObject3D(SphereObject3D po3d){
spherePool.addLast(po3d);
}

public class SphereObject3D extends BranchGroup {
Transform3D translate = null;
TransformGroup tg = null;

public SphereObject3D(float rad, Appearance ap){
translate = new Transform3D();
translate.set(new Vector3f(-1,-1,-1));
tg = new TransformGroup(translate);
tg.addChild(new Sphere(rad, ap));
addChild(tg);
setCapability(BranchGroup.ALLOW_DETACH);
}
public void setPosition(Vector3f pos){
translate.setIdentity();
translate.set(pos);
tg.setTransform(translate);
}
}

public static void main(String argv[]) {
new MyFrame();
}
}

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
Anonymous

Are there any plans of making Java3d work independant of any Canvas3d? Or some kind of work-around making that possible?

I'm toying with a project, a client-server based game, where I'm looking to have Java3d handle not only rendering graphics on the client, but also take care of collisions, picking etc server side.
Is this kind of solution going to be possible in the future, without forcing the server to run a small "debug window" as I do now?

Thanks for any help..

Justin Couch

java3d-interest@javadesktop.org wrote:

> Are there any plans of making Java3d work independant of any Canvas3d? Or some kind of work-around making that possible?
>
> I'm toying with a project, a client-server based game, where I'm looking to have Java3d handle not only rendering graphics on the client, but also take care of collisions, picking etc server side.
> Is this kind of solution going to be possible in the future, without forcing the server to run a small "debug window" as I do now?

No there isn't, as the refresh timing on the canvas is what drives the
rendering implicitly (way oversimplifying how it all works). The more
important limitation is that, due to the AWT requirements, your server
has to be running an X-windows client. I believe they fixed this for the
JDK 1.5 release and you can run in headless mode, but check to make sure.

--
Justin Couch http://www.vlc.com.au/~justin/
Java Architect & Bit Twiddler http://www.yumetech.com/
Author, Java 3D FAQ Maintainer http://www.j3d.org/
-------------------------------------------------------------------
Programming is essentially a markup language surrounding
mathematical formulae and thus, should not be patentable.
-------------------------------------------------------------------

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

Anonymous

Yes, you can run AWT as "headless" through the java.awt.headless system property:
System.setProperty("java.awt.headless", "true");
We're using this in another project that involves resizing images, running on a linux machine without X.

But if that bug (4727054) is fixed, isn't there some other way to "fake" the refresh timing? Say by linking the VirtualUniverse to a Canvas3d that's not placed in any Frame, then somehow keep forcing that canvas to refresh itself in regular intervals?

Just curious about what techniques might be available, or if I should just rewrite my server and skip the 3d-engine stuff there, try to write some kind of picking algorithm myself.

Kevin Rushforth

This is a known limitation of Java 3D (Bug 4727054: Memory leak when all
windows containing Canvas3Ds are minimized).

Java 3D uses a message-based update system for scene graph updates. If
you throttle the consumer of messages (the renderer), by minimizing
(iconifying) the window, without throttling the producer (your main
thread), you will eventually run out of memory. For this reason, as well
as for performance (it's wasteful to send many more times the number of
updates than can be displayed in a single frame time), it is recommended
that you update the scene graph from a behavior, rather than from a
free-running thread. Failing that, you should check whether the Canvas3D
that is attached to the view you are updating is visible and throttle
your scene graph updates.

Btw, as hurkules mentioned, we will be somewhat slow in answering
messages over the next couple of weeks...

-- Kevin

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

rdlecler
Offline
Joined: 2004-05-17
Points: 0

Thanks for the input. My fix for this was to remove the root "scene" BranchGroup from the Universe whenever the window is iconified, lost focus, etc, and to add the "scene" back to the universe object whenever it was deiconified, focus was regained etc.

Best,
RDL

ada_s_o
Offline
Joined: 2006-02-14
Points: 0

Please, I need to remove the root "scene" BranchGroup from the Universe, how I doing this?

I have some error whit a loader "DXF" the error is "0utOfMemoryError" then I believe, If I remove the "scene" sometimes solution my problem.

Someone has some Suggestion?

scidocks
Offline
Joined: 2003-06-12
Points: 0

I'd be curious to introduce a sufficient time delay between each successive add/detach in the innermost loop, and see how it goes.

rdlecler
Offline
Joined: 2004-05-17
Points: 0

One thing I did notice which was a bit weird was after I let it ran for awhile and then closed the window there was a good 10-20 seconds or so before the heap started to increase in size. Opening the window again it stabablized but at a higher memory footprint. It was a bit strange that there was a long delay between closing the window and an increase in memory size.

rdlecler
Offline
Joined: 2004-05-17
Points: 0

Yes, I think this is a cache that is being reset only when the canvas is visible.

I tried to manually trace through the source code but eventually got lost and I couldn't figure out where this cache might be getting saved. Maybe if I don't get a response i'll actually download the source and trace through it in the debugger.

I am going to post this as an issue, assuming of course that I didn't just forget to set some flag somewhere.

Best,
RDL

herkules
Offline
Joined: 2003-06-12
Points: 0

Don't be too impatient about the answer .... the Java3D guys are at JavaOne now and announced to go on holiday after that....

herkules
Offline
Joined: 2003-06-12
Points: 0

Sounds like something is added to the rendering queue that cannot be evaluated bc. the window is closed (and thus no rendering takes place)

rdlecler
Offline
Joined: 2004-05-17
Points: 0

I just realized that this memory leak only appears when the window is closed. I was running it for awhile with the window open and it seemed to hit a pretty steady memory footprint, but as soon as I closed the window it show through the roof and crashed on me shortly after.

rdlecler
Offline
Joined: 2004-05-17
Points: 0

You will notice that if you take out the lines where you add and remove to the scene, as well as the call to detach you dont get the memory leak even though you are still allocating the new Vector3f objects, thus I had ruled out the possibility that Vector3f wasn't being gced.

Best
RDL