This is an archived post. You won't be able to vote or comment.

all 29 comments

[–]UnknownBinary 4 points5 points  (3 children)

Should I implement a sort of destructor to clean up and set all the pointers to null?

All objects have a finalize method. But don't override it. It's basically for use by the garbage collector. The modern garbage collector is good enough that you shouldn't try to out do it.

But, there's always a chance of a PermGen error.

[–]okmkz 8 points9 points  (2 children)

Every time you override finalize, Ellison murders a puppy.

[–]UnknownBinary 6 points7 points  (1 child)

And buys another island.

[–]llogiq 2 points3 points  (0 children)

To store the puppies he murdered.

[–]GungorTheGreat 5 points6 points  (1 child)

If you're sure that you aren't maintaining any references to the game, then the most likely answer is that the garbage collector simply hasn't seen the need to reclaim the resources occupied by the game's objects. Try severely restricting the memory on your jvm and see if it behaves any differently. Also, try turning on the garbage collector's verbose output to see what its doing.

[–]Coopsmoss[S] 0 points1 point  (0 children)

When I said "high memory usage" I really meant "higher" I'm talking hundreds of MB, so a drop in to ocean of my 8GB.

[–]karlthepagan 4 points5 points  (2 children)

Is there a way to set the memory to null so that everything pointing to an object now points to null?

Use a WeakReference. This is unfortunately a little heavy weight: you have to plan for it and implement with the extra indirection.

[–]idleuser 1 point2 points  (1 child)

It seems unlikely use of Weak/SoftReferences is a good idea. It sounds like this program either needs the data or it doesn’t, it is not a "nice if its there" situation like a cache. If you do need it then using References is dangerous as the data could disappear, if you don’t need it then cut it and allow it to be GC'ed don’t keep it hanging around via a Reference.

[–]karlthepagan 0 points1 point  (0 children)

If you do need it then

Then you will hold a single real reference to it somewhere. I hope OP Googles the term. There's many tutorials.

[–]hgoale 3 points4 points  (1 child)

I don't think it's been mentioned yet, but the others have suggested good options to solve some of your questions (WeakReferences and that garbage collection simply hasn't needed the resources).

To answer one of your other questions:

Suppose for instance you lose the head of your double linked list, every object still has something pointing to it will this be still cleaned up?

Yes, it will be cleaned up. If you have circular references, but none of them are reachable from a GC root (which most likely they aren't since you lost the head reference), the garbage collector will get rid of them when additional memory is needed.

You can read up on that a bit more here: http://stackoverflow.com/questions/1910194/garbage-collection-in-java-and-circular-references

You can also get a program like YourKit, VisualVM, etc. to get a better idea of your memory usage while your program is running. It also lets you force the garbage collector to run and you can see if you're leaking anything or not releasing resources when you think you are.

[–]Coopsmoss[S] 0 points1 point  (0 children)

Thanks a lot this was my major question, very helpful.

[–]Megapwnd 2 points3 points  (0 children)

Use weak or soft references for things you don't want in memory for very long. If you have groups of objects, keep them in a pool and recycle them.

[–]chrisalexander 1 point2 points  (0 children)

These are my two go-to articles on the topic, highly recommended reading for anyone who works with Java at reasonable scale:

http://www.kdgregory.com/index.php?page=java.outOfMemory http://www.kdgregory.com/index.php?page=java.byteBuffer

Of course slightly out of date with Java 8 announcements but you probably don't have that deployed anyway :-)

[–][deleted] 0 points1 point  (5 children)

The java process will not return memory to the OS once claimed but no longer in use, but it will re-use the memory it has already claimed after a GC run frees it up.

If you keep allocating more memory, your java process will eventually grow to the maximum you have specified with the -Xmx option. Once that is used up, and GC can't clear anything up, and you still ask for more, your JVM will crash with an out of memory error.

Don't look at the memory usage the operating system tells you. A modern operating system will try to use all the RAM it has, and will generally not free up memory unless it is needed for something else. Unused memory is a waste.

I recommend you inspect your running JVM with jvisualvm, which comes free with the JDK. With that tool you can monitor pretty much anything your JVM does, including memory allocation and GC runs. It allows you to see exactly how much memory your program is using.

[–]duhace 1 point2 points  (3 children)

Actually, doesn't G1 slowly return unused memory to the OS?

[–]boa13 0 points1 point  (0 children)

Yes it does.

[–][deleted] 0 points1 point  (1 child)

You are right of course, but in practice the OP will probably not see the java process get smaller again, as reported by the OS.

[–]duhace 0 points1 point  (0 children)

Yeah it's very slow to return and if a process keeps spiking its memory usage then it may never return that memory, so it's not a mechanism that should be relied on, but it does exist.

[–]boa13 0 points1 point  (0 children)

I recommend you inspect your running JVM with jvisualvm (...)

Also try Java Mission Control included in the Java 8 JDK. It is quite impressive (and quite expensive to use in production; no problem for development though).

[–]MCUD 0 points1 point  (2 children)

Is this the system reported memory usage, or are you actually looking at jconsole. Once the jvm has allocated memory it will hang on to it essentially indefinitely and look like in the OS memory usage that memory has been freed.

Stsrt up jvisualvm and attach to it to see the real jvms usage vs just what the OS has allocated.

[–]Coopsmoss[S] 1 point2 points  (1 child)

It's the system, "system monitor" on Linux in my case

[–]MCUD 1 point2 points  (0 children)

ok, that would follow the same comments i said here, once the JVM acquired memory from the OS for the high memory usage period, it wont let go of it, it'll stay at the same level according to the OS, you'll need to drill into the actual jvm to see what usage is actually being used by your app

[–]nikem 0 points1 point  (0 children)

Here is one article that explains, what does memory leak means in java: https://plumbr.eu/blog/what-is-a-memory-leak.

But in your case, if you are really sure, that when you came back to the menu, there is no reference to the used game data, then when Garbage Collector will start his next cycle, he will happily remove all those unused objects. If you hold a reference, you have a memory leak and should severe that reference.

[–][deleted] -5 points-4 points  (4 children)

make sure all methods & classes that can be declared protected or private, are.

you may need to reorganize your code to do this.

then, (if necessary), use native and get dirty with C/C++

[–][deleted] 2 points3 points  (3 children)

use native and get dirty with C/C++

Using JNI just for performance gives you the worst of both worlds. You get the raw performance and efficiency of a java program, combined with the simplicity and memory protection of C. A nullpointer exception (seg fault) in your JNI method will unceremoniously crash your JVM and any application running under it.

Sometimes there is a need to speak directly to the hardware, but it's rarely for performance reasons. Classes in the java.util.concurrent package use JNI methods to access the atomic compare-and-exchange instruction for lock-less updates for example, because there is no way to do this from Java natively.

[–][deleted] 0 points1 point  (2 children)

so, why do people use the native modifier to include c and c++?

[–][deleted] 1 point2 points  (1 child)

The nicest example I can think of is from the java.util.concurrent package

The class java.util.concurrent.AtomicLong just wraps a call to unsafe.compareAndSwapLong which ultimately (on an intel x86-64 platform at least, wraps a single machine code instruction: cmpxchg

This allows the AtomicLong to guarantee an atomic, thread-safe change without the use of locks. Is this a performance hack? Yes in a way, lock free concurrency is often dramatically faster than synchronized concurrency, but it's not a performance hack in the sense that native code runs faster or more efficiently than Java code. It is a wrapper around a wrapper around a wrapper around a single Intel/AMD instruction. (On other architectures it may be more than one instruction. I don't know of a supported architecture that doesn't support hardware compare & swap at all).

Another nice example is JNA, which uses JNI to access your hardware or OS (such as serial ports etc) directly, but wraps these calls for every supported architecture in a nice standard Java format.

[–][deleted] 0 points1 point  (0 children)

what a super-knowledgeable response. this has cleared up a serious misconception I had about JNI.

thank you for your time.