For a group project at university we chose to use Java and Java3D. Java3D is one of the implementations of 3D graphics available for Java. It works through OpenGL and is around 25% slower than pure C via OGL. This means that speed isn’t a problem; we are only using it for a university project and polygon counts are low. Java3D, however, has a much more insidious problem: it leaks memory like hell.
To begin with, the approach adopted was to create a level and then free it when the level is completed (or allow the garbage collector to clean up after us). For each level, it seemed that a few megabytes of memory were lost. This happens even when calling various methods listed as allowing J3D to reclaim resources in the API documentation. To begin with, I just thought it was my coding skills: I haven’t done much 3D coding so I’m probably just forgetting a vital detail.
I start to google on the problem to try and find the obvious thing that I missed. A more worrying picture appeared, however. It turns out that, no matter how hard you try, Java3D will leak memory. It takes copies of various data structures and is notoriously bad at freeing them. This was not good, as it meant our game crashed with an Out of Memory error after ten or fifteen levels. Clearly not good enough for a demonstration situation where it should run for a couple of hours.
So, without further ado, I set about trying to workaround this problem. Firstly, I implemented caching for all the models used in the program. This increased the time until crashing to fifty or so levels. An improvement, but still not enough.
Looking closer into the levels, it appeared that there was not much done to initialise the levels in addition to building the scene-graphs. This suggested that it might be possible to cache the levels, removing all level object-construction after the first playing of each level. Fortunately the rest of our game is structured in such a way that allowed for this to be implemented fairly easily. This means that the game no longer crashed, at least for the couple of hundred levels I left it running for. It is not an ideal situation though, the need to cache levels. It leads to more memory being used than should be used, as we should be able to clean up each level fully after use. It is an improvement, however, on an ever increasing memory load leading to a crash.
Java3D is a nice API to program with once you understand its way of working. It is a shame that it still seems to be rather buggy. We uncovered many smaller bugs in the API when using it. Various default implementations are far slower than they need to be. For example, overlaying images onto a 3D scene is actually faster if you create a shape in the 3D scene and texture map your image onto the shape than if you use the Canvas3D objects native overlay methods. Most bugs have a workaround, but for a 1.4 version of the API I would expect better performance. I did enjoy using it though, so I hope the bugs get ironed out by the next time I use it.