Why the method call System.gc() doesn't guarantee that the Garbage Collector algorithm will run at that moment? Why it cannot certainly reclaim all unused object's memory whenever it is invoked ?
Forcing object destruction is sign of bad coding so Java might wanted to avoid developers from getting addicted to it.
If Java gives you freedom of forcing of object destruction, improper use of it might have adverse affect of application performance.
This restriction allows you (force you) to put more focus into business logic than memory managemnt
JVM is the best person to decide when memory management is required and how to do it.
You can (should) trust JVM and let it handle things in better way than we can.
Still do you really want to force object destruction? If yes, WHY?
In order to ensure that programs run smoothly within the JVM, the JVM itself manages garbage collection.
Garbage collection has become quite sophisticated. When you ask the system for a GC run, which algorithm are you expecting? A "full GC"? There are multiple heaps, as well; which one is the garbage you are concerned about on? You don't know and this method doesn't indicate.
Suppose calling System.gc() always triggered a full GC. An errant program could easily grind JVM performance to a halt. Defensively, the JVM would want to limit the frequency at which it responded to such calls.
If you are running in a JVM on a non-embedded system (e.g. a server or a desktop computer), there should be no reason for you to concern yourself with any aspect of memory management other than to monitor it and code efficiently.
There are several metrics that are utilized to evaluate garbage collector performance , some of them are:
Throughput—the percentage of total time not spent in garbage collection, considered over long periods of time.
Garbage collection overhead—the inverse of throughput, that is, the percentage of total time spent in
garbage collection.
Pause time—the length of time during which application execution is stopped while garbage collection is occurring.
Frequency of collection—how often collection occurs, relative to application execution.
Footprint—a measure of size, such as heap size.
Promptness—the time between when an object becomes garbage and when the memory becomes
available.
Now If JVM listens to System.gc() like good pet and guarantees to perform action on each System.gc() call, Imagine what would be the performance of application if it is called many times within program.!!??
Throughput will decrease
Garbage Collection overhead will increase.
Application will pause many times as it is busy in recollecting the memory.
If Footprint is large , The garbage Collector would have to scan all memory area for recovering the memory , no matter if there are objects eligible for garbage collection or not.
So , after looking through these points I guess it provides the sufficient reason to JVM to not respond to System.gc on the application choice , but on its own algorithm. And Garbage Collection reclaims all unused object's memory for sure , but its invocation is entirely dependent on JVM own Algorithm rather than on the user's choice.
Source: Memory Management in the Java HotSpot™ Virtual Machine - Sun Microsystems
it cannot certainly reclaim all unused object's memory whenever it is invoked
This assumption of yours is false. In most cases the Garbage Collector could reclaim all unused objects at any point in time. However, if the standard Java library provided a method that would guarantee that, it would put a completely unreasonable burden on the GC subsystem to provide a service that is most of the time useless and could be even damaging.
Related
Is there any condition when application will never perform Garbage Collection ? Theoretically is it possible to have such application design ?
Yes, there is. Please read about memory leaks in Java. An example is described in Effective Java Item 6: Eliminate obsolete object references
Garbage collection happens on objects which are not referenced anymore in your application.
With Java 11, there is a way to never purposely perform garbage collection, by running your JVM with the newly introduced Epsilon GC, a garbage collector which handles memory allocation but never releases the allocated memory.
There is at least one product in the market that implements high frequency trading using Java and jvm technology.
Obviously, an application that needs to react in microseconds can't afford a garbage collector to kick in and halt the system for arbitrary periods of time.
In this case, the solution was to write the whole application to never create objects that turn into garbage. For example, all input data is kept in fixed byte arrays (that are allocated once at start time) which are then used as buffers for all kinds of processing.
Unless I am mistaken, you can listen to more details on the software engineering radio podcast. I think it should be this episode: http://www.se-radio.net/2016/04/se-radio-episode-255-monica-beckwith-on-java-garbage-collection/
Is there any condition when application will never perform Garbage Collection ?
You can prevent the GC from running by having a Thread which doesn't reach a safe point.
Unless you use a concurrent collector, the GC will only be performed when a memory region, e.g. when the Eden or Tenure spaces fill.
If you make these large enough, and your garbage rate low enough, the GC won't run for long enough that you can either perform a GC overnight, in a maintenance window or restart the process.
Theoretically is it possible to have such application design?
I have worked on applications which GC less than once per day (and some of them are restarted every day)
For example, say you produce 300KB of garbage per second, or 1 GB per hour, with a 24 GB Eden size you can run for a whole day without a collection.
In reality, if you move most of your data off-heap e.g. Chronicle Map or Queue, you might find a 4 GB, can run for a day or even a week with a minor collection.
I know that the garbage-collection is used to get rid of the orphaned objects (the ones that loses their references) but is it possible to set custom intervals for garbage-collecting in Java?
It is not advisable for an application to tell the GC to run. It is better to leave it to the JVM to make the decision.
Why?
Because the JVM knows best. The JVM has access to information that allows it to run the JVM at the best time, to optimize either for high throughput or low pause times. It can monitor the size of the various heap "spaces", and estimate the best time to initiate a collection, and what kind of collection to initiate. The decision making is complicated.
By contrast, if an application calls System.gc() on a fixed time interval, it may run when it doesn't need to, using CPU cycles unnecessarily. Indeed, if you run the GC when there is no garbage, it spend a lot of time scanning all of the live objects ... and then not achieve anything.
The other thing to note that if System.gc() is not ignored, a common behavior is to run a full garbage collection. Depending on your JVM's GC options, this may cause all application threads to be frozen. If the heap is large, the "GC pauses" for full collections can be significant.
Another answer suggests using the sun.rmi.dgc.client.gcInterval property. This is designed to deal with the collection of remote references in an RMI application. It may work in other contexts, but it is inadvisable for the reasons stated above.
Using Runtime.getRuntime().gc() or System.gc() you can suggest JVM for garbage collection but you cannot set intervals or call it in any way
public static void gc()
Calling the gc method suggests that the Java Virtual Machine expend effort toward recycling unused objects in order to make the memory they currently occupy available for quick reuse. When control returns from the method call, the Java Virtual Machine has made a best effort to reclaim space from all discarded objects.
The whole point of a garbage collection is, that the developer does not need to worry about the memory management whatsoever (as always there might be exceptions, but these are rare)
As pointed out you can only suggest the JVM to trigger the GC from your java code.
If you have problems with your GC interval, maybe you can instead set some parameters to your JVM?
Maybe you can use the parameter:
gcInterval(ms) = max interval between GC
But I have never used it myself, so no experience on this one.
This is not a duplicate as the thread mentioned as duplicate only tells you why to not use System.gc(), while I do know that, that's not my question.
Using System.gc() or Runtime.getRuntime().gc() won't always execute garbage collection, it just requests it and it can even be ignored by the JVM.
Is there a reason behind this? Is it "random"? Since I don't think random even exists in programming, I'm curious why it sometimes doesn't collect it, and sometimes does and also at different times.
Yes. There is a very good reason.
First you need to understand a couple of facts about garbage collection in general:
Running the garbage collector is expensive.
Running the garbage collector (repeatedly) at the wrong time can be catastrophically inefficient1.
Next to impossible for a typical application to predict when the GC can be run most efficiently.
So to your questions:
Using System.gc() or Runtime.getRuntime().gc() won't always execute garbage collection, it just requests it and it can even be ignored by the JVM. Is there a reason behind this?
Yes. It is primarily to guard against the catastrophic behavior effects that naive programmers can cause by calling gc() at the wrong time.
Is it "random"?
Nope. It is nothing to do with randomness.
In practice, typical JVMs have a command line switch that determines whether gc() calls are ignored, or not. This allows the user / deployer / integrator / whoever to mitigate the poor choice made by the programmer.
But note that it cannot be overridden from Java code. That would defeat the purpose of making this a command line switch.
I'm curious why it sometimes doesn't collect it, and sometimes does and also at different times.
The normal behavior of a JVM is to try to run the garbage collector when it is most efficient to do so. The JVM can optimize two ways:
It can optimize to maximize the throughput of the collectors; i.e. to minimize the CPU time spent on collection
It can optimize to minimize the length of GC pauses; i.e. the times where the JVM has to freeze all application threads during the collection.
It is complicated. From the perspective of an external observer (who / which doesn't have access to the heap stats, etcetera) it may be hard to understand why the GC runs at a given point in time. But is certainly not random.
1 - One of the counter-intuitive properties of a GC algorithm is that the cost of collecting is (in most cases) dominated by the costs of tracing non-garbage objects and moving in memory to coalesce the freed space. So if you call the GC when there is not much garbage to collect, you will end up tracing / moving large amounts of non-garbage for little actual benefit. By contrast, the JVM has a better insight on when it is a good time to collect. For a start, it knows how much space is left in each pool at any point in time.
As well as being counter-intuitive, this behavior gets worse as the heap gets bigger. So a programmer can write code that uses gc() in the wrong way, and not notice that there is a performance problem. The performance only becomes an issue when the application is run with a production workload / problem size. Combine this with the effects of using the heap to cache things, and / or memory leaks.....
I have developed a J2ME web browser application, it is working fine. I am testing its memory consumption. It seems to me that it has a memory leak, because the green curve that represents the consumed memory of the memory monitor (of the wireless toolkit) reaches the maximum allocated memory (which is 687768 bytes) every 7 requests done by the browser, (i.e. when the end user navigates in the web browser from one page to other for 7 pages) after that the garbage collector runs and frees the allocated memory.
My question is:
is it a memory leak when the garbage collector runs automatically every 7 page navigation?
Do I need to run the garbage collector (System.gc()) manually one time per request to prevent the maximum allocated memory to be reached?
Please guide me, thanks
To determine if it is a memory leak, you would need to observe it more.
From your description, i.e. that once the maximum memory is reached, the GC kicks in and is able to free memory for your application to run, it does not sound like there is a leak.
Also you should not call GC yourself since
it is only an indication
could potentially affect the underlying algorithm affecting its performance.
You should instead focus on why your application needs so much memory in such a short period.
My question is: is it a memory leak when the garbage collector runs automatically every 7 page navigation?
Not necessarily. It could also be that:
your heap is too small for the size of problem you are trying to solve, or
your application is generating (collectable) garbage at a high rate.
In fact, given the numbers you have presented, I'm inclined to think that this is primarily a heap size issue. If the interval between GC runs decreased over time, then THAT would be evidence that pointed to a memory leak, but if the rate stays steady on average, then it would suggest that the rate of memory usage and reclamation are in balance; i.e. no leak.
Do I need to run the garbage collector (System.gc()) manually one time per request to prevent the maximum allocated memory to be reached?
No. No. No.
Calling System.gc() won't cure a memory leak. If it is a real memory leak, then calling System.gc() will not reclaim the leaked memory. In fact, all you will do is make your application RUN A LOT SLOWER ... assuming that the JVM doesn't ignore the call entirely.
Direct and indirect evidence that the default behaviour of HotSpot JVMs is to honour System.gc() calls:
"For example, the default setting for the DisableExplicitGC option causes JVM to honor Explicit garbage collection requests." - http://pic.dhe.ibm.com/infocenter/wasinfo/v7r0/topic/com.ibm.websphere.express.doc/info/exp/ae/rprf_hotspot_parms.html
"When JMX is enabled in this way, some JVMs (such as Sun's) that do distributed garbage collection will periodically invoke System.gc, causing a Full GC." - http://static.springsource.com/projects/tc-server/2.0/getting-started/html/ch11s07.html
"It is best to disable explicit GC by using the flag -XX:+DisableExplicitGC." - http://docs.oracle.com/cd/E19396-01/819-0084/pt_tuningjava.html
And from the Java 7 source code:
./openjdk/hotspot/src/share/vm/runtime/globals.hpp
product(bool, DisableExplicitGC, false, \
"Tells whether calling System.gc() does a full GC") \
where the false is the default value for the option. (And note that this is in the OS / M/C independent part of the code tree.)
I wrote a library that makes a good effort to force the GC. As mentioned before, System.gc() is asynchronous and won't do anything by itself. You may want to use this library to profile your application and find the spots where too much garbage is being produced. You can read more about it in this article where I describe the GC problem in detail.
That is (semi) normal behavior. Available (unreferenced) storage is not collected until the size of the heap reaches some threshold, triggering a collection cycle.
You can reduce the frequency of GC cycles by being a bit more "heap aware". Eg, a common error in many programs is to parse a string by using substring to not only parse off the left-most word, but also shorten the remaining string by substringing to the right. Creating a new String for the word is not easily avoided, but one can easily avoid repeatedly substringing the "tail" of the original string.
Running System.GC will accomplish nothing -- on most platforms it's a no-op, since it's so commonly abused.
Note that (outside of brain-dead Android) you can't have a true "memory leak" in Java (unless there's a serious JVM bug). What's commonly referred to as a "leak" in Java is the failure to remove all references to objects that will never be used again. Eg, you might keep putting data into a chain and never clear pointers to the stuff on the far end of the chain that is no longer going to be used. The resulting symptom is that the MINIMUM heap used (ie, the size immediately after GC runs) keeps rising each cycle.
Adding to the other excellent answers:
Looks like you are confusing memory leak with garbage collection.
Memory leak is when unused memory cannot be garbage collected because it still has references somewhere (although they're not used for anything).
Garbage collection is when a piece of software (the garbage collector) frees unreferenced memory automatically.
You should not call the garbage collector manually because that would affect its performance.
I have a strange doubts. I know garbage collector has its own limitation. and if allocation is
bad then it can cause a problem for application to respond in unusual way.
So my question is that is it good programming habit to call forcefully garbage collector (System.gc()) at the end of each activity?
Update
Every one is saying that calling system.gc() not beneficial at all.Then i am wondering why its present here.DVM will decide when to run garbage collector.Then what is need of that method?
Update 2
Thanks community to help me out. But honestly i got knowledge about Garbage collection real Beauvoir from this link Java Performance Optimization
it isn't good programming habit to call forcefully garbage collector (System.gc()) at the end of each activity
Because it is useless,only DVM decide when it should be call although you called it...
System.gc(), which the VM sometimes ignores at whim, is mostly useful in two cases:
you're gobbling up memory like there's no tomorrow (usually with bitmaps).
you suspect a memory leak (such as accidentally holding onto an old Context), and want to put the VM memory in a quiescent state to see if the memory usage is creeping up, for debugging.
Under nominal circumstances, one should not use it.
I really think it depends on your situation.
Because the heap is generational, the GC may not get rid of certain large objects or bitmaps on its first pass, and its heuristics may not indicate that additional garbage collection is necessary, but there are definitely scenarios where the heuristic could be wrong, and we as the developers have knowledge of a pattern, or can predict usage that the GC cannot, and therefore calling system.gc() will benefit us.
I have seen this before in specific scenarios such as dealing with map tiling or other graphic intensive behaviors, where the native GC in Android (even on 3.0+ devices), doesn't get it right, resulting in Out of Memory errors. However, by adding a few GC calls, the Out of Memory errors are prevented, and the system continues to process albeit at a slower rate (due to garbage collection). In graphic intensive operations, this usually is that state desired (a little lag) over the application crashing because it cannot load additional resources into memory.
My only explanation for why this happens in certain scenarios appears to be timing. If user operations are slow, then the native Android GC seems to do great. However, if your user is scrolling fast, or zooming quickly, this is where I have seen the Android GC lag behind, and a few well thought out System.gc() have resulted in my applications not crashing.
calling System.gc(), doesn't do any harm. but you cant be sure that it will be of some use. because you ask the DVM to do garbage collection, but can't command it... Its dependent totally on DVM. It calls when memory is running out or may be at any time..
I tried putting System.gc() on the line before the lines where I created my bitmap in my Android app. The garbage collector freed up several megabytes in some cases and put and end to my OutOfMemoryError conditions. It did not interfere with the normal garbage collection one bit but it did make my app run faster.
No; if the system needs memory, it will call GC on its own.
Any memory used by an instance, that isn't referenced anywhere else, will become eligible for GC when the instance goes away.
Memory used by the instance itself, if no longer referenced, is also eligible for GC. You can do a code review or profiling to see if you're holding on to memory unnecessarily, but that's a different issue.
Calling GC manually is a bad coding habit...
The Developer docs on RAM usage state:
...
GC_EXPLICIT
An explicit GC, such as when you call gc() (which you should avoid calling and instead trust the GC to run when needed).
...
I've highlighted the most important and relevant part here in bold.
It is possible to ask the Android JVM to run the garbage collector by calling System.gc(). As the documentation states:
Calling the gc() method suggests that the Java Virtual Machine expend effort toward recycling unused objects in order to make the memory they currently occupy available for quick reuse. When control returns from the method call, the Java Virtual Machine has made a best effort to reclaim space from all discarded objects.
Emphasis added!
Some care is needed in interpreting "best effort" in the final sentence:
The "best effort" might be to ignore the "suggestion" entirely. Some JVMs have a configuration option to totally ignore System.gc() calls.
The "best effort" may or may not amount to a full garbage collection. That is an implementation detail.
But the bottom line is that you cannot force the GC to run.
Calling System.gc() is generally a bad idea. It makes your application inefficient, and it may introduce unwanted and unnecessary GC pauses.
The inefficiency issue comes down to the way that modern garbage collectors behave. A garbage collector's work has two parts1:
Finding the objects that are reachable.
Dealing with the objects that are not reachable.
The first part involves traversing reference chains and and marking the graph of objects starting at the GC roots. This work is proportional to the number of reachable objects.
The second part can be handled in a couple of ways, but it will typically be proportional to the size of the reachable objects.
Thus the overall cost of a GC run (in CPU time) depends mostly in the amount of non-garbage. But the benefit of the work performed is the amount of space that you managed to reclaim.
To maximize efficiency, you need to run the GC when the benefit of running the GC is at its highest; i.e. when the heap is close to full. But the problem is that if you call System.gc() you may be requesting a garbage collection when there is lots of free space.
Every one is saying that calling system.gc() not beneficial at all. Then I am wondering why its present here. DVM will decide when to run garbage collector. Then what is need of that method?
It is there for largely historical reasons. The method was present in the System class in Java 1.0. Removing it now would break a lot of legacy code. As for why gc() was included in the first place, the decision was made a long, long time ago, and we were not "in the room" when it was made. My guess is that the decision makers (in ~1995):
were a bit too optimistic about how GC technology would develop,
didn't anticipate that naive programmers would try to use gc() calls to solve memory leaks and other bugs, and / or
were simply too rushed to think too hard about it.
There are also a couple of scenarios where calling System.gc() is beneficial. One such scenario is when your application is about to start a "phase" where unscheduled GC pauses are going to give a particularly bad user experience. By running System.gc() you can take the "performance hit" at a point in time where it matters less; e.g. during a user initiated pause or while switching levels in a game.
But I don't think the above scenario corresponds to your "at the end of every activity".
The final thing to note is that calling System.gc() manually does not prevent normal OOMEs. A normal OOME is typically thrown then the JVM decides there is not enough free heap space to continue. This decision is made immediately after running a (full) GC. Running System.gc() manually won't make any difference to the decision making.
Furthermore, calling System.gc() will not cure normal2 memory leaks. If your application has a memory leak, you actually have a situation where a bunch of objects are reachable when they shouldn't be. But since they are reachable, the GC won't delete them.
The cure for OOMEs is one or more of the following:
Find the memory leaks and fix them. There are tools to help you do this.
Modify the application to use memory more efficiently; e.g. don't keep so much data in memory, or represent it in a more compact form.
Increase the application's heap size.
1 - This is a simplification, but the full story is way to complicated for this posting. I recommend you buy an read an up-to-date book on Garbage Collection of you want (or need) a deeper understanding.
2 - There are cases involving non-heap memory where manually running the GC might help as a band-aid for certain kinds of OOME. But a better solution is to find a better way to reduce non-heap memory usage and/or free up non-heap resources in a more timely fashion.