Java doesn't suffer from circular references in the way you might expect - two objects mutually referring to one another won't stop both of them being collected as garbage if noone else can access them. Java uses a reachability check to guarantee this.

There is a "sort-of" delete() method in Java, called finalize(). It is called exactly once before first garbage collecting an object, and allows the developer to perform any cleanup required. However, it is rarely used and is unlikely to be what you're after here.

If you allocate lots of new objects, Java will likely use RAM up (without freeing old objects) until it isn't allowed any more - there's no point in performing any collection unless there's a need for it, after all. Are you actually getting OutOfMemoryErrors, or are things just using up more memory than your system is comfortable with?

Take a look at the command-line JVM flags if you do wish to modify Java's memory settings.

And use a profiler to see if your objects are really still "anchored" and referenceable.

Memory leaks can't happen in Java, but what we call "Object Leaks", which are user-error in leaving an object refrenceable, happen more often then people realize.

Also be sure to close any system objects which have a close() (or dispose() ) method that you are using when done with them. Some of our API implementations hang onto references in inobvious ways. (For instance, you need to close an ObjectOutputStream or it keeps a reference to every object written to it.)

Got a question about Java and game programming? Just new to the Java Game Development Community? Try my FAQ. Its likely you'll learn something!

Only if something else is holding a reference to the Engine. If nothing else does, Engine will get collected which in turn will mean that nothing is left to point to Car, and hence it will get collected.

Clearly you are used to a reference counting solution to determining garbage. In reference counting, circular references are an issue because each one keeps the other alive.

(It's worth noting though that even in your car-engine case above, as soon as you break one link in the circle, its not a problem. Car references Engine. Engine references car. That will stay around in reference counting situation because both objects have a count of one. if however you null Car's reference to Engine, Engines count drops to 0. Engine is freed. When Engine is free ITS reference to Car goes away so Car's count drops to 0 and Car is also freed.)

HOWEVER reference counting is a very primitive soulutions for garbage detection. More sophisticated solutions (such as used by Java) actually trace reference trees back to "root" objects that process can start a reference chain from (eg static variables, class variables, instance variables or temporary variables currently active on the stack.) If the object is not reachable from one of them, it is marked as garbage and eventually collected.

In your earlier example, if Car or Engine were an object instance variable then both would stay HOWEVER if your object instance contained a list of cars, that was the only "root" reference to Car, there were no "root" references to Engine except through Car, and you removed Car from the List, Car AND Engine would get marked as garbage and, should the need for memory arise, collected.

See?

Got a question about Java and game programming? Just new to the Java Game Development Community? Try my FAQ. Its likely you'll learn something!

A couple of points on cleanup we follow, after some experience cleaning up memory in a medium sized application ...

- nulling out variables is bad. It can convey state, it can be used to trigger lazy instantiation, but as a general rule it leads to null pointers. It has never fixed a memory leak for me, but it has minimized the scope of a memory leak. (see point below). Where state info is desired there is always a better way, especially if you're masking an exception. Threadsafe objects tend to be immutable, so this is more possible & desirable than you might think.

- Minimizing the impact of a leak I think is a valid reason to set things to null, some object trees are huge. A better solution for minimizing the scope of a leak would be to use an empty object aka MyBigClass.NULL_OBJECT. It's the same thing as passing around empty arrays instead of null objects, things break less and the size of leaks are minimized. I would only employ this strategy on items with potential for big leaks.

- oh yeah, don't touch finalize with a ten foot pole. If you can find another way use it. Overriding any method that is only called 1/3 of the time is asking for trouble.

Memory cleanup is important, and should be designed in. What I look for in a class cleanup ....

1. It has one of dispose(), cleanUp() or add/removeNotify(). .. although I recommend against the last option, no one seems expect the override of the notify methods, and so they are never maintained right.

2. It removes all listeners, it empties all collections and arrays, closes any I/O streams, it can be called safely multiple times (important! no one should be afraid to call cleanup methods).

Can we alter the timing of when the JVM starts its garbage collection.Meaning if every five minutes it will do garbage collection, then can I alter it to be do it every 2 minutes instead?

The short, flippant, answer is: Sure, reduce the size of the Java heap and the GC will run more frequently.

The longer, and probably more correct, answer is: Control of the GC is probably best left to the JVM. Feel free to call System.gc() between levels or in some similar game down-time, it's only a suggestion to the JVM and it can't hurt. Worrying about precisely when a full GC will occur is counter-productive... unless you have profiled extensively and you know for a fact that the GC is a problem for you.

As to explicitly null-ing object references: It can't hurt and it probably makes the intent of your code more obvious. I doubt, however, that it has a huge impact on performance. Note that I am in no way a JVM engineer, and so speak with no authority on this matter. The JVM does seem to optimise the most clear method of doing things (witness object pooling: used to be a necessary evil, now considered just plain evil in most cases), so write your game in the most clear and expressive way possible for now. Optimise proven bottlenecks later.

int[] array = new int[60MB worth of integers];array = null <-- GC will occour at this line is it? or does it GC after the new object which is at the next line?array = new [60MB worth of integers];

GC happens when the allocation of the second array is started, and the VM notices that there is not enough memory to allocate it. No GC happens at the "array = null" line itself. It just removes the reference to the array, and the array will stay in memory for an undefined time before it is collected.

java-gaming.org is not responsible for the content posted by its members, including references to external websites,
and other references that may or may not have a relation with our primarily
gaming and game production oriented community.
inquiries and complaints can be sent via email to the info‑account of the
company managing the website of java‑gaming.org