How to verify/force classes to be garbage collected - java

I'm in a scenario where I launch applications in a specific Classloader by a entry point defined API, something like "OSGi". And I have made specific methods such as: start and stop. And the applications launched are in an array called applications.
If I want to end the application I would call the stop method of it. However suppose the application is a malicious and it doesn't clean it's class/resources, how can I force it to be garbage collected???
If I do a simple applications[i] = null; on the main application, will it force that malicious application who didn't clean any resource to be garbage collected???

If the only reference to the applications is held in applications[i], then this will be needed. However the next GC cycle can't be predicted. So the application may have a longer lifetime than expected

No, you can't tell the garbage collector to force collect a specific object. Setting a reference to null doesn't guarantee anything.
You could run your potentially malicious application in a separate process and terminate the process when you have finished with it. Then the operating system will ensure that all resources (memory and other resources) are freed.

The garbage collector will collect unused objects (objects without reference, that is) on its own. It can't be forced, it can't be predicted well. It can however be asked to run by invoking
System.gc()
Note that this does not garantee anything either, it merely "suggests" that the garbage collection should begin.
But this is genereally considered bad practice because it can seriously impact the performance of the garbage collection process and the JVM.
So in most cases it is best to insure that there are no references left so the object can be collected when the GC deems it appropriate.

Related

Out of memory errors in Java API that uses finalizers in order to free memory allocated by C calls

We have a Java API that is a wrapper around a C API.
As such, we end up with several Java classes that are wrappers around C++ classes.
These classes implement the finalize method in order to free the memory that has been allocated for them.
Generally, this works fine. However, in high-load scenarios we get out of memory exceptions.
Memory dumps indicate that virtually all the memory (around 6Gb in this case) is filled with the finalizer queue and the objects waiting to be finalized.
For comparison, the C API on its own never goes over around 150 Mb of memory usage.
Under low load, the Java implementation can run indefinitely. So this doesn't seem to be a memory leak as such. It just seem to be that under high load, new objects that require finalizing are generated faster than finalizers get executed.
Obviously, the 'correct' fix is to reduce the number of objects being created. However, that's a significant undertaking and will take a while. In the meantime, is there a mechanism that might help alleviate this issue? For example, by giving the GC more resources.
Java was designed around the idea that finalizers could be used as the primary cleanup mechanism for objects that go out of scope. Such an approach may have been almost workable when the total number of objects was small enough that the overhead of an "always scan everything" garbage collector would have been acceptable, but there are relatively few cases where finalization would be appropriate cleanup measure in a system with a generational garbage collector (which nearly all JVM implementations are going to have, because it offers a huge speed boost compared to always scanning everything).
Using Closable along with a try-with-resources constructs is a vastly superior approach whenever it's workable. There is no guarantee that finalize methods will get called with any degree of timeliness, and there are many situations where patterns of interrelated objects may prevent them from getting called at all. While finalize can be useful for some purposes, such as identifying objects which got improperly abandoned while holding resources, there are relatively few purposes for which it would be the proper tool.
If you do need to use finalizers, you should understand an important principle: contrary to popular belief, finalizers do not trigger when an object is actually garbage collected"--they fire when an object would have been garbage collected but for the existence of a finalizer somewhere [including, but not limited to, the object's own finalizer]. No object can actually be garbage collected while any reference to it exists in any local variable, in any other object to which any reference exists, or any object with a finalizer that hasn't run to completion. Further, to avoid having to examine all objects on every garbage-collection cycle, objects which have been alive for awhile will be given a "free pass" on most GC cycles. Thus, if an object with a finalizer is alive for awhile before it is abandoned, it may take quite awhile for its finalizer to run, and it will keep objects to which it holds references around long enough that they're likely to also earn a "free pass".
I would thus suggest that to the extent possible, even when it's necessary to use finalizer, you should limit their use to privately-held objects which in turn avoid holding strong references to anything which isn't explicitly needed for their cleanup task.
Phantom references is an alternative to finalizers available in Java.
Phantom references allow you to better control resource reclamation process.
you can combine explicit resource disposal (e.g. try with resources construct) with GC base disposal
you can employ multiple threads for postmortem housekeeping
Using phantom references is complicated tough. In this article you can find a minimal example of phantom reference base resource housekeeping.
In modern Java there are also Cleaner class which is based on phantom reference too, but provides infrastructure (reference queue, worker threads etc) for ease of use.

Garbage collector don't run when object is referenced.Which object?

As there are so many objects being created for a particular class some of which could be referenced and some can be anonymously lying in the heap and hence elgible for garbage collection . So is the presence of even one non referenced object in the heap is enough for garbage collector to run or is there any other criteria to assure the garbage collector is executed.
Thanks
Jayendra
we don't know when GC get executed, it depend on lots of things e.g. Type of GC. Also you can recommend to VM to launch GC by doing System.gc(). But again it is just a recommendation
GC on an object is, for typical reference implementations of the JVM, completely non-deterministic. There is no way to guarantee when, or even if, the GC will be run, never mind if it will result in a particular object reference being released (and its corresponding finalizer called.) This is regardless of the state of this particular object.
As pointed out in comments, System.gc() is merely a hint or request. In a great many cases it will result in a full GC. But consider gathering a heap dump usually results in 2-3 calls to System.gc() before the dump is generated, mostly as a way to improve the chances it actually happens.
There are experimental VMs that offer various implementations of real-time guarantees where some of this is not true.

garbage collector doubts

I have some question over here regarding the java garbage collector.
First let me clear what I have understood regarding the Java GC.
GC is a background thread will always run in the background when the JVM starts.
Each object having one finalize() method. This method is used to release the
system resources before the object is destroyed. According to java experts,
we should not put the resources under finalize() method for releasing the
system resources. Becuase we cannot make sure when the GC will run. But we can
request the GC to run by calling System.GC().
So now my question is, GC is a background thread will always run in the background.
Now how can we say that we dont know when the GC will run? Is the statement like this "we dont know when the GC will call finalize() method "
Is that the meaning of that? If that is what they meant, then what is the job
of GC? GC's responsibility to find out the un used variable and remove from the memory.
In that case,why GC cannot call finalize() method also?
Now how can we say that we dont know when the GC will run?.
Functioning of GC is dealt by complex Algos, which is dependent on underlying OS and Hardware. WE can't say because if one tell about a particular JVM version it will not be valid with other JVMs. So it better we can't rely on that.
what is the job of GC.
GC finds reference less objects (read type of ref. for more) and reclaims memory used by them.
n that case,why GC cannot call finalize() method also?
So that's sure finalize method will be called but it's not sure when. Because evenif you know in your JVM when finalize() method will run, you never know when in other JVMs. So, if you deal with some really expensive resources in your finalize method, your programe may crash in other JVMs.
Simply put, GC will run at an indeterminate time, so system resources would not be freed in a timely manner if finalize is relied on to free them. It doesn't make sense to wait for the GC to reap the heap space of an object holding a system resource when most program logic should be easily designed to simply release the resource when it is no longer in use.
On a somewhat related note. One of the issues that caused early versions of the JVM to be so slow was calling finalize. Thus, modern JVMs will skip calling finalize whenever possible. So relying on finalize could also have a performance impact.

Preventing native memory leak by customizing garbage collector?

Let's say I'm writing an API in java that refers to some native C libraries, that requires destructors to be called explicitly. If the destructors are not called, I run out of native memory.
Is there a way to protect users of my API from calling the destructors explicitly, by having the garbage collector call the destructors somehow? (perhaps based on some estimate I make of the size of the used native memory?)
I know Java doesn't have its garbage collector as part of the Java API, but perhaps there is some way to get this implemented?
One alternative if you have control over creation of your objects is to reference them with a WeakReference using the constructor that takes a ReferenceQueue. When they get out of scope, the Reference will be queued and you can have your own thread polling the queue and call some clean up function.
Why?
Well, it is slightly more efficient than adding finalizers to your classes (because it forces the gc to do some special handling of them).
Edit: The following two (variations of the same article) describes it:
http://java.sun.com/developer/technicalArticles/javase/finalization/
http://www.devx.com/Java/Article/30192
Peter Lawrey has a very good point when he says:
Even so, waiting for the GC to cleanup can be inefficient and you may want to expose a means of explicitly cleaning up the resource if its required.
Whenever you can assume your users to be on Java7, take a look at java.lang.AutoCloseable as it will help them do that automatically when using the new try-with-resources.
In addition to use finalize(), you may need to trigger a GC if you run out of resources to make the call, however a GC hasn't been run.
The ByteBuffer.allocateDirect() has this issue. It need the GC to clean up its ByteBuffers, However, you can reach your maximum direct memory before a GC is triggered, so the code has to detect this and triggers a System.gc() explicitly.
Even so, waiting for the GC to cleanup can be inefficient and you may want to expose a means of explicitly cleaning up the resource if its required.
Garbage collector will call finalize() of Java objects when the Java object is about to be GCd, and inside the finalize, you could call the destructor. Just make a new Java object for every destructor that needs to be called, and keep reference to that Java object until when you want to call the destructor.
In practice, finalize() will be called sooner or later (even though technically Java makes no guarantee that any particular object will ever be GCd). The only exception is if the object is still around when the process is shutting down: then it may indeed never get GCd.

Java garbage collection

Java automatically calls garbage collector, then why we need manual calls for garbage collection? When should use System.gc()
Java automatically calls garbage collector, then why we need manual calls for garbage collection?
We don't need them. Indeed, in most circumstances calling System.gc() is harmful for application performance. See my answer to "Why is it a bad practice to call system gc" for a detailed explanation.
When should use System.gc()
If the application knows it is going into a phase where it has nothing else to do AND the user is unlikely to notice a garbage collection, then maybe it is OK call to System.gc() in an effort to stop the user experiencing GC pauses in the future.
The downsides include:
Calling System.gc() typically triggers a full GC which takes significantly longer than a GC of the 'new space'.
The user may actually care / notice. For example, if you call System.gc() between "levels" in a game, you make loading the next level take longer.
By forcing the GC, you are causing the JVM to use extra CPU cycles, etc which may potentially interfere with other things that the user is doing on his machine.
(There can also be legitimate reasons to call System.gc() in unit tests, and during system debugging.)
There isn't a need to call for garbage collection explicitly and calling System.gc() is only a suggestion, the JVM can ignore your suggestion.
The only practical uses I can think of is
During debugging, forcing a collection can expose a memory leak
If the program goes through predictable cycles of intense computation followed by no computation (like a turn based game), during the no-computation period the CPU could be utilized for a suggested garbage collection to prevent jitter during the intense computation portions.
System.gc() is only a suggestion. But it does make sense in some situations.
Suppose you have class MyClass, and you're wondering how much memory does one instance take. What you can do is this (roughly speaking):
MyClass [] objects= new MyClass[100000];
System.gc();
long memoryNow = Runtime.getRuntime().freeMemory();
for (int i = 0; i < 100000; i ++) {
objects[i] = new MyClass();
}
System.gc();
long memoryLater = Runtime.getRuntime().freeMemory();
int objectSize = (int)((memoryLater - memoryNow) / 100000);
There are other similar cases I've found System.gc() to be useful.
One aspect not yet mentioned is that some types of objects may ask entities outside themselves to do things on their behalf (e.g. give them exclusive access to a non-fungible resource like a file), to the detriment of other entities. When a garbage-collection is performed, the system will not only free up memory that was formerly occupied by unreachable objects, but it will also call finalize on objects that it notices have been abandoned, thus allowing such objects to notify outside entities that their services are no longer required. It is entirely possible for a program to reach a state where there's plenty of memory, but a necessary resource is unavailable because an object has been granted exclusive access and has since been abandoned without releasing it. Forcing the garbage-collector to run in such a situation may sometimes free up the necessary resource.
The garbage collector is always called by the JVM when there is not enough memory to allocate new objects into the heap. While calling the garbage collector, it follows the Stop the World norms and for this it calls the System.gc() method.
Also remember that the JVM also runs parallel gc threads to remove unused objects from memory . So everything and every minute JVM maintains heap memory and always tries to not overload it. So there is no any requirement to explicitly call System.gc() or Runtime.gc() method.
If you want more detail about this you can get here for the relevant information.
Garbage collection process is not under the user's control.So it makes no sense to call System.gc(); explicitly. It entirely depends on the JVM.
Few days back, I had asked exactly the same question : [Here].
In fact, many questions related to calling System.gc(); explicitly have been already asked and answered here. Calling System.gc(); explicitly is always considered as poor programming skill, although it won't do any harm.
Here are the few links that I you should go through it. It will definitely clarify your doubt.
Calling System.gc(); explicitly
Bad practise - Calling System.gc();
System.gc(); in java
PS : Btw, you should seriously take
the extra effort to go through
similar StackOverflow questions before posting about your doubts.
There is no need to call System.gc() or Runtime.getRuntime().gc(). The JVM internally controls garbage collection if it finds that it is running out of memory.

Categories