Below is a copy of a post someone put to this group in 1998!!! There was no answer in that thread and searching the archives I have not yet found an answer...so, I'm going to ask you all about it. Do you know how to get back the memory after removing a child from a parent?
Hi, I did some test and I found almost the same thing.
I start the program where just one shape is added. Mem is 1100 Then i add 500 new shapes, call gc, and the memory goes to 2200. Now I remove all the shapes, call gc, and memory goes up to 2700 (???) I add and remove shapes, call gc, and memory goes up and down, from 2700 to 4000.
If I add more shapes (es. 10000) the result is similar but more memory is "lost" when all the shapes are removed.
The only thing i noticed is that the arraylist that contains the children of shapeRoot (see code) is not trimmedToSize after childern are removed, so it remains to full size. I do not think this can explain the full thing cause i think the array internal to arrayList hold just the space for the references and not for full objects (even it would be nice to have even those few bytes back).
Then i tryed not to call gc and the results are incredible :) Memory goes down even to 330. Sometimes adding or removing cause memory to go up to 2200, other times it falls back to 400. On average it stays around 800/1400.
So...do not call gc :)
PS I know that scenegraph should be modifyed only from the processstimulus of a behavior but I hope this is not relevant in this case.
Bye
package mesh;
import java.applet.Applet;
import java.awt.*;
import java.awt.BorderLayout;
import java.awt.GraphicsConfiguration;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.geometry.*;
import com.sun.j3d.utils.geometry.NormalGenerator;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
public class HelloUniverse extends Applet {
private SimpleUniverse u = null;
private BranchGroup shapeRoot;
Button b = new Button("ADD");
final int COUNT = 500;
boolean added = false;
public HelloUniverse() {
}
private void addShapes() {
System.out.println("Adding....");
for (int i = 0; i < COUNT; i++) {
BranchGroup group = createShape();
shapeRoot.addChild(group);
}
b.setLabel("REMOVE");
System.out.println("Added");
}
private void removeShapes() {
System.out.println("Removing...");
shapeRoot.removeAllChildren();
b.setLabel("ADD");
System.out.println("Removed");
}
private Runtime rt = Runtime.getRuntime();
private void dumpMem() {
System.out.println("1. " + (rt.freeMemory()/1000) + "/" + (rt.totalMemory()/1000));
System.gc();
System.out.println("2. " + (rt.freeMemory()/1000) + "/" + (rt.totalMemory()/1000));
}
public BranchGroup createSceneGraph() {
BranchGroup objRoot = new BranchGroup();
//here i add my test shapes
shapeRoot = new BranchGroup();
shapeRoot.setCapability(BranchGroup.ALLOW_CHILDREN_EXTEND);
shapeRoot.setCapability(BranchGroup.ALLOW_CHILDREN_WRITE);
//add a shape just to load all classes
objRoot.addChild(shapeRoot);
BranchGroup group = createShape();
shapeRoot.addChild(group);
objRoot.compile();
return objRoot;
}
public BranchGroup createShape() {
float[] vertex = { 0.5f, -0.5f, 0, //centro
-0.5f, 0.5f, 0,
-0.5f, -0.5f, 0,
0.5f, 0.5f, -0.4f, //secondo fan
-0.5f, 0.5f, 0 };
GeometryInfo geomInfo = new GeometryInfo(GeometryInfo.TRIANGLE_FAN_ARRAY);
geomInfo.setCoordinates(vertex);
geomInfo.setStripCounts(new int[]{5});
NormalGenerator ng = new NormalGenerator();
ng.generateNormals(geomInfo);
GeometryArray tFan = geomInfo.getGeometryArray();
Shape3D shape = new Shape3D(tFan);
BranchGroup group = new BranchGroup();
group.setCapability(BranchGroup.ALLOW_DETACH);
group.addChild(shape);
return group;
}
public void destroy() {
u.removeAllLocales();
}
public void init() {
setLayout(new BorderLayout());
GraphicsConfiguration config =
SimpleUniverse.getPreferredConfiguration();
Canvas3D c = new Canvas3D(config);
add(BorderLayout.CENTER, c);
add(BorderLayout.SOUTH, b);
b.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
if (added)
removeShapes();
else
addShapes();
added = !added;
//remove comment to call gc
//dumpMem();
}
});
Button gc = new Button("GC");
add(BorderLayout.NORTH, gc);
gc.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
dumpMem();
}
});
Button mem = new Button("MEM");
add(BorderLayout.EAST, mem);
mem.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
System.out.println("mem " + (rt.freeMemory()/1000) + "/" + (rt.totalMemory()/1000));
}
});
BranchGroup scene = createSceneGraph();
u = new SimpleUniverse(c);
u.getViewingPlatform().setNominalViewingTransform();
u.addBranchGraph(scene);
}
public static void main(String[] args) {
new MainFrame(new HelloUniverse(), 512, 512);
}
}
