I wrote an app for the production team to measure their scores, it runs fine for 2-3 weeks and then the开发者_StackOverflow machine that the copies are running on slows down and a restart fixes it.
What are the best practice steps for fixing this?
You need to analyse the Heap and find out what objects are being retained in there that shouldn't be.
One option:
Try reducing the -Xmx
max heap size to expedite an out of memory exception, add this option to the jvm at startup -XX:+HeapDumpOnOutOfMemoryError
and then load the heap dump that is generated into something like Eclipse Memory Analyzer.
Another option:
Dump the heap from your running process using jmap (probably needs sudo privileges)
jmap -heap:format=b <pid>
and again, load the heap dump binary into jhat or Eclipse Memory Analyzer.
If your app is slowing down but not throwing an OutOfMemoryError it is likely that you don't have a leak but you do need to do some JVM tuning because it's spending too much time doing GC.
You should be monitoring GC collection times (you can log them using -Xloggc:/tmp/gc.out
) or you can use jstat
to see how often GC takes place and how long it takes.
If you have an application with lots of medium lived objects is the Young Generation big enough (-XX:NewRatio=N
) ? If not your app will spend to long promoting objects to the old gen only to have to GC them shortly after (GC in old gen is expensive relative to New Gen, especially when you have fragmented memory).
Also - have you enabled the CMS collector? If you have a multi-core machine I suggest you do (-XX:+UseConcMarkSweepGC
).
There are no memory leaks in Java in the traditional sense unless you are using JNI.
Memory leak in Java usually refers to creating referenced objects that you are no longer using. The symptom typically is that the memory usage of the application keeps growing. Do you see the memory usage growing?
You would do well to search for the exact same question in Google and follow the links.
The best practice to address is it usually to use a Profiler to check your allocations. It may also point at performance bottlenecks not caused by the "memory leaks"
You can check the memory the JVM requires by using an OS utility such as a task manager or top
.
You can use a profiler to check the memory of your java code, e.g. Java VisualVM.
Keep in mind that Java uses garbage collection, so the only way of "memory leakage" is by holding references to (a lot of) unused objects. Josh Bloch's Effective Java item 6 (Eliminate obsolete object references) explains these situations and how to prevent them very well.
You can also use further methods to check for this kind of "memory leakage", e.g. static analysis and pluggable type systems or jvm memory options.
One good thing to track down memory issues is to enable garbage collection logging by adding the following commands to java at startup -verbose:gc
-XX:+PrintGCDetails
and -XX:+PrintGCTimeStamps
. Then you can analyze how the garbage collector behaves, i.e. how often the GC is running, how long time it takes for the garbage collector to reclaim memory, how much memory is being reclaimed and if the used memory of your application is increasing.
Here's a document explaining the gc logging output: GC tuning guide for Java 6
精彩评论