In graalvm project, gc is written in java in substratevm. What makes me curious is how to manage the memory of a garbage collector written in a language with gc.
If he manages his own memory by himself, it may cause an infinite loop. Here I assume that the garbage collector includes the functions of memory allocation and recovery, and give an example.
For example: My code is a garbage collector-> I need to create an object and allocate memory-> I called the garbage collector (myself)-> I need to create an object and allocate memory > I called the garbage collector (myself) ......
How does it solve infinite loop problems? My idea is to use a lightweight garbage collector written in an additional local language (like C language) to run itself (garbage collector written in java). Although substratevm seems to be compiled into a local executable binary file in native-image, I think the problem still exists.
SubstrateVM GC is written in a subset of Java that has a few restrictions. One of them is that GC code never allocates memory on the Java heap -- see com.oracle.svm.core.heap.RestrictHeapAccess.NO_ALLOCATION. That makes sense as GC is often started in response to the heap being full, so it would not be able to allocate anything anyway. Instead it requests memory chunks directly from the OS using mmap and the like -- see CommittedMemoryProvider and VirtualMemoryProvider classes
Related
I knew that there are a lot of articles about java garbage collection but after searching I don't know exactly "when dose the garbage collection run in a java application?(when the application restart or while it still running)".
Garbage Collector is a dameon thread. A dameon thread runs behind the application. It is started by JVM. The
thread stops when all non-dameon threads stop.
The JVM controls the Garbage Collector; it decides when to run the Garbage Collector. JVM runs
the Garbage Collector when it realizes that the memory is running low. The behavior of GC can
be tuned by passing parameters to JVM.
One can request the Garbage Collection to happen from
within the java program but there is no guarantee that this request will be taken care of by
jvm.Check How to force garbage collection in Java?
Learn More ..
Garbage collection runs regularly alongside the program. It is part of the JVM.
When exactly does it run though? Well, that's unpredictable, version-dependent, and should be treated as if it could run at any time.
When a variable goes out of scope, the application tells the JVM it's done with that piece of memory. Then, when the garbage collector runs it will free those resources for the OS to use.
For example
String capitalizeAll(String s) {
char[] chars = s.toCharArray();
for(int i = 0; i < chars.length; i++)
chars[i] -= 32;
return new String(chars);
}
As soon as the method returns, the char[] chars allocated within the method will go out of scope. The program tells the JVM it's done with those resources and next time GC runs they will be freed.
Interesting stuff though, the JVM takes into account how much the app has told it is ready to be collected. That means that if your app does a lot of unnecessary copying or boxing, JVM will run often and cause your app to take a performance hit.
This is mostly implementation-specific.
The most primitive type of garbage collector, the serial GC will be triggered when it fails to find sufficient free space during an allocation (with generational GCs this usually means the young generation is full). It then suspends the entire JVM by triggering a safepoint on mutator threads and does its work on a single thread, this is called a "stop the world pause"
In this case you can say that GCs can be caused by any allocation.
On top of that some GCs may also do background work concurrently to mutators, such as Hotspot's CMS. But it still needs stop the world pauses for some work, they just tend to be shorter than in the serial GC.
For CMS it's still triggered by allocations but also does some of its work on background thread(s).
Azul Zing's concurrent compacting collector also does - as its name says - concurrent collecting on dedicated threads more or less all the time. It still needs cooperation from the mutator threads but does so without STW pauses.
So this case one could say that the GC is running all the time in the background and does a little work in the foreground.
There are other collectors out there, so this isn't a comprehensive overview. But in general it's an implementation detail, subject to change and not something one should rely on. Some GCs even ignore System.gc() by default because it would mess up their heuristics.
This is from Kathy Sierra and Bert Bates' book SCJP Study Guide:
"The garbage collector is under the control of the JVM. The JVM decides when to
run the garbage collector. From within your Java program, you can ask the JVM to
run the garbage collector, but there are no guarantees, under any circumstances, that the JVM will comply. Left to its own devices, the JVM will typically run the garbage collector when it senses that memory is running low. Experience indicates that when your Java program makes a request for garbage collection, the JVM will usually grant your request in short order, but there are no guarantees. Just when you think you can count on it, the JVM will decide to ignore your request."
I am a newbie to Java. I understand what garbage collection and paging, swapping do in isolation. I wanted to understand how they relate to each other. Does GC cause paging or swapping? I know that the primary job of GC is to reclaim memory. But does it reclaim by paging or swapping if needed or is it not relevant to GC and is done by OS?
To understand the relation, note that Java performs generational garbage collection. There is a young and and old generation of objects allocated on the heap. From the JVM's point of view, it will not care about swapping but use the heap size it was configured with. However, the heap size will of course dictate the swapping behaviour of the OS that manages the JVM process.
In the young generation's collection, only rather new objects are collected. These objects should not have been swapped out by the OS due to their recent allocation. Of course, if you chose a size bigger than your RAM for your young generation, swapping will be required even for collecting the young generation what will slow down your garbage collector.
In the tenured generation, the performance of garbage collection will firstly depend on the strategy for collection. Consider a naive algorithm that performs a full garbage collection. This algorithm will have to check the entire application's object graph what requires access to the entire JVM heap. Obviously, the entire heap should fit into the RAM. Otherwise, a lot of swapping will be required for garbage collection what will result in a bad performance. In reality, the collector will not check the entire object graph. However, it remains a good practise to choose a heap size that fits into your RAM in order to avoid excessive swapping when for example configuring a Java application's production server.
Actually, I am a newbie in Java world too. I come here because I get confused with this just like you. However, if you thinking about the mechanism of swapping, you may find the difference between swap and garbage collection. swapping is a behaviour of operator system. and garbage collection is a behaviour of Java jvm which is a process/thread of the system.
So, swapping and garbage collection is different level thing. If memory is not enough, swapping will happen to figure out memory that unused temporary and then swapping out.
Above all, swapping may happen before full GC. and at the same time, garbage collection i.e. full gc. also may happen without swapping. A simple example is that: we config the JVM with a small heap size . bug we allocate a large buffer space, at this situation, full GC may happen and also OOM may happen.
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'm allocating a lot of byte buffers. After I'm done with them I set all reference to null. This is supposedly the "correct" way to release bytebuffers? Dereference it and let the GC clean it up ? I also call System.gc() to try and help it along.
Anyways, I create a bunch of buffers, deference them; but after "some time" I get all sorts of memory errors: java.lang.OutOfMemoryError: Direct buffer memory
I can increase the MaxDirectMemorySize but it just delays the above error.
I'm 99% positive I don't have anything referencing the old ByteBuffers. Is there a way to check this to see what the heck still has a ByteBuffer allocated?
You can use a tool like MAT that's free with Eclipse to see what is keeping your byte buffer by letting it do some heapdump analysis.
Another way I can think of is to wrap your byte buffer with something else that has a finalizer method.
Also Systen.gc() does not guarantee that finalizers will be executed you need to do System.runFinalization() to increase the likelihood.
Setting the references to null is the correct way to let the garbage collector that you are finished with that object. There must still be some other dangling reference. The best tool I have found for finding memory leaks is YourKit. A free alternative that is also very good is Visual VM from the JDK.
Remember that the slice() operation creates a new byte buffer that references the first one.
This is a problem with older versions of Java. The latest version of Java 6 will call System.gc() before throwing an OutOfMemoryError. If you don't want to trigger a GC you can release the direct memory manually on the Oracle/Sun JVM with
((DirectBuffer) buffer).cleaner().clean();
However, it is a better approach to recycle the direct buffers yourself so doing this is not so critical. (Creating direct ByteBuffers is relatively expensive)
Direct java.nio.ByteBuffer is (by definition) stored outside of java heap space. It is not freed until GC runs on heap, and frees it. But you can imagine a situation where heap usage is low therefore it does not need GC, but non-heap memory gets allocated and runs out of bounds.
Based on very interesting read:
http://www.ibm.com/developerworks/library/j-nativememory-linux/
The pathological case would be that the native heap becomes full and
one or more direct ByteBuffers are eligible for GC (and could be freed
to make some space on the native heap), but the Java heap is mostly
empty so GC doesn't occur.
There was a comment in the question calling-system-gc-explicitly stating that "You can not "force" a generic JVM to do garbage collection because a garbage collector is not actually required by the JVM spec.". My question is if there's such a JVM (and how and where does it get used, if so).
For instance, JavaCard's JVM lacked garbage collection until v3.
Garbage collection (if you ignore weak and soft references) is roughly a simulation of having infinite memory, at least for objects that are unreachable. If an object gets garbage collected in the woods and no code can reach it, did it make a sound?
In practice, JVMs without collectors would be few and far between because in practice memory is limited. About the only places I can think of where a JVM without a GC would be useful would be a research/learning JVM, or a JVM used only for very short-lived processes (where you know you'll destroy the entire JVM before it consumes too much memory).