I have a method that create some heavy objects as cache. This objects are rarely accessed, but expensive and slow to process, and are initialized only on demand. Then on use my application, for instance, I could request about three heavy object like that, and reuse them, but too is possible that I run it once and it only occupy memory while I never use it anymore during a session.
My question is: is possible I define that an object is "garbage collectable", then in case of application requires more memory it unset this unused data?
I think that it should works something like that (pseudo-code):
private static MyInstance instance = null;
public static getInstance() {
if (instance == null) {
instance = calculate();
GC.put(instance);
}
return instance;
}
I think that I can do it with some kind of Timer, then check from time to time, but I guess that Java should have something like that, to call only if memory is heavy used.
Yes, Java offers three types of indirect references which are sensitive to memory usage.
A cache can use a SoftReference that will be cleared before the process raises an OutOfMemoryError. As long as there is plenty of memory, however, the SoftReference will prevent its referent from being garbage collected.
Java does not have a way to manually de-allocate memory (see Memory Management in Java. However, it does have automatic garbage collection. This means that any object that has no references left in the program will be automatically removed. In your case, for example, if an Instance is no longer used (the function that used it returns, and no other references exist, or you overwrite the sole variable that stored a reference to the Instance with something else), that Instance will be garbage-collected.
There is not, however, any method of making the Instance disappear any faster than getting rid of references to it, and letting the garbage collector deal with it.
What I would suggest instead, for your application, is something like an LRU cache (see How would you implement an LRU cache in Java?), which would restrict your memory usage to a set number of instances, which (depending on what exactly Instance is) would limit you to a set amount of memory used by Instances.
If you wanted instead to allow any amount of memory to be used, but not used for very long, you could create a wrapper class for Instance, which implements your cache idea (only creates an Instance when called, if its current copy is null), but keeps a timer and sets its Instance to null after a given amount of time has expired without it being used.
What you need is a proper cache implementation. There are tons of them in Java, e.g., Guava Cache, which is highly configurable.
Your calculate method is just CacheLoader#load.
You don't need to care about the GC. Just size your cache properly so that not too much memory gets used. Evicted cache entries get collected automaticaly (when not referenced elsewhere).
I think that I can do it with some kind of Timer, then check from time to time, but I guess that Java should have something like that, to call only if memory is heavy used.
You can use time based eviction with e.g. CacheBuilder#expireAfterWrite. There's no caching in Java itself, but there's SoftReference. Anyway, I don't recommend using it directly, but consider using it with CacheBuilder#softKeys.
Related
Let's consider following code:
class Table {
private static int number_of_Tables=0;
public Table(){
++number_of_Tables;
}
public void finalize(){
--number_of_Tables;
}
public static int current_TableCount(){
return number_of_Tables;
}
}
What I want to achieve is that when Garbage Collector (GC) destroys the Object that the count of available Objects gets decreased by one.
But everyone here on topic of finalize() is saying that using this method is very bad because following could happen: even though there are no references pointing to the object the GC may not destroy it immediately because GC doesn't work around the clock i.e GC will be invoked after certain amount of object are there to be destroyed i.e at certain times GC will perform the cleanup, which means that even though the object is not available anymore my counter wouldn't decrease and I would give the false information upon invoking the method curret_TableCount()
What do people do instead, to solve this kind of a problem with certainty?
There must be some kind of solution in Java?
EDIT: I need to recognize when the object is not referenced anymore i.e during runtime there exists not even one pointer(reference) to the object when this is true, i would then decrese the number of that kind of objects by one.
…following could happen: even though there are no references pointing to the object the GC may not destroy it immediately because GC doesn't work around the clock
That’s correct. The garbage collector’s purpose is to manage memory and only to manage memory. As long as there are no memory needs, the garbage collector doesn’t need to run. It’s perfectly possible that an application runs completely without any gc cycle, when there is sufficient memory.
Further, there is no guaranty that a garbage collector run identifies all unreachable objects. It might stop its work when it identified enough reclaimable memory to allow the application to proceed.
This, however, is not the only issue. Often overlooked, the fact that the garbage collector only cares for memory needs, implies that an object may get collected even when being in use, when its memory is not needed anymore, which is possible with optimized code. This is not a theoretical issue. See for example this bug or that bug related to naive dependency on finalization, even in JDK code.
Note that even if finalize() happens to get invoked at the right time, it’s invoked by an unspecified thread, which requires using thread safe constructs.
What do people do instead, to solve this kind of a problem with certainty?
People usually don’t have that kind of problem. If you truly manage a non-memory resource, you should use an explicit cleanup action, i.e. a method like dispose() or close(), to be invoked after use. The straight-forward approach is to let the class implement AutoClosable (or a subtype of it) and use the try-with-resources statement.
Cleanup actions triggered by the garbage collector are only a last resort for dealing with scenarios where the explicit cleanup has been forgotten. As explained, implementing them needs special care.
In case of a counter maintained only for statistics, you may simply live with the fact that it is imprecise. Normally, you don’t need to know how many instances of a class exist. If you really need it, e.g. when trying to debug a memory leak, you can take a heap dump, a snapshot of all existing objects, and use a dedicated analysis tool.
Say i have a class, which loads a file and then calls another method to do something to that file. For example, counting the words in the file.
Within class CountWords, a number of objects/collections are created in order to get the number of words. The method runs, the number of words is found, and then this is returned to the calling class.
My question is, do all the objects/collection created in the CountWords class get "destroyed" when control is returned to the calling class or do they remain in the memory? If the latter, would i have to set each object to null before exiting the class to mark them for collection?
We don't generally control exactly when a Java object gets destroyed. It will get destroyed some time after it becomes inaccessible - in other words, when there are no further references to it in any scope.
If you create an object, and store a reference to it in a field of another object, then the object you created continues to be accessible for as long as the object that has the reference to it is accessible.
If you have code like this
public void run() {
Foo a = new Foo();
System.out.println("This method is finished");
}
then the Foo that you created will be inaccessible as soon as run finishes, because there are no more variables with references to it. Foo will be destroyed some time afterwards. Unless of course, the constructor of Foo does some magic to register itself in some nasty static data store somewhere.
So in general, you don't need to go round setting references to null to destroy objects. From the point of view of the garbage collector, letting those references go out of scope is just as good as setting them to null.
Java is a programming language that has memory management aka garbage collection. The basic answer is, the garbage collector will take care of reclaiming the memory of unused objects.
But since you have tagged the question with [garbage-collection], you should already know this. So it’s not clear what additional detail you want to know or why you think your scenario is special in any way, to deserve an additional answer beyond “there is a garbage collector”.
You question is full of phrases that are wrong or misguiding.
“do object references get destroyed”—the storage of objects is reclaimed, there is no such thing as “destruction of references”
“when the creating class is closed”—there is no such thing as “closing of classes”
“do all the objects/collection created in the CountWords class get ‘destroyed’ when control is returned to the calling class or do they remain in the memory?”—in this form, not simple to answer
there is no such thing as “destruction”. The whole purpose of garbage collection is to permit the reuse of the memory. This implies recording somewhere that the memory is free. But the memory itself does not need to be touched.
when your method returns, these objects are eligible for garbage collection. The garbage collection itself does not have to run immediately. It may happen when there is need for free memory or when the CPU load is low.
As said, even if the garbage collector ran, the result is that the memory is now considered to be free, not necessarily to “scrub” the memory. So the objects may “remain in the memory” until actually being overwritten by other objects. So that’s simply the wrong question. You actually want to know whether the memory will be reusable.
“If the latter, would i have to set each object to null before exiting the class to mark them for collection?”—“the latter” still implies that the memory is free, semantically. But what do you want to “set to null”? The references do not exist anymore. The objects are unreachable.
The answer is there is nothing you can do and there is nothing you should do. That’s the whole point of garbage collection, no need for you to do anything.
We don't need to set the objects to null after coming out the function . For this Java have garbage Collector , which runs on the Java Virtual Machine which gets rid of objects which are not being used by a Java application anymore. It is a form of automatic memory management.
For example :
for (int i =0 ; i<10 ; i++) {
String s = String.valueOf(i)
}
In the above code, the integer s is being created on each iteration of the for loop. This means that in every iteration, a little bit of memory is being allocated to make a integer object.
Going back to the code, we can see that once a single iteration is executed, in the next iteration, the integer object that was created in the previous iteration is not being used anymore -- that object is now considered "garbage".
Eventually, we'll start getting a lot of garbage, and memory will be used for objects which aren't being used anymore. If this keeps going on, eventually the Java Virtual Machine will run out of space to make new objects.
That's where the garbage collector steps in.
The garbage collector will look for objects which aren't being used anymore, and gets rid of them, freeing up the memory so other new objects can use that piece of memory.
Automatic memory management schemes like garbage collection makes it so the programmer does not have to worry so much about memory management issues, so he or she can focus more on developing the applications they need to develop.
I am wondering whether you would consider it a good practice to remove references (setting them to null) to objects in order to help the Java Garbage Collector.
For instance, let's say you have a class with two fields, one of them being very memory-consuming. If you know you only need it for a particular processing, you can null it right after to help the GC.
Assume I really need those two to be fields, and not only internal variables, so heavyObject1 cannot be out of scope at the end of the method.
Would you do this as a general practice?
public class TestClass {
public static Object heavyObject1;
public static Object object2;
private static void action() {
object2 = doSomething(heavyObject1);
heavyObject1 = null; //is this good?
}
}
Usually it isn't needed.
It's a good idea in the following specific circumstance:
The object is large (i.e. large enough for you to care)
You are sure the object won't be needed again
The object won't go out of scope otherwise (e.g. you know the surrounding object won't be garbage collected)
However if you find yourself in this situation I suspect you have a design smell anyway: why does the internal object have such a different scope / lifetime from the enclosing object? This makes me suspicious, because usually when you build up an object graph with composition you expect the composed objects to have similar lifetimes.
In most of the cases, you dont need to set the object to null to be garbage collected.If you decalre the object in proper scope(method level,instance level or class level), the object will be unreachable immediately after its use and will be eligible for garbage collection.
It's certainly not bad practice to assign null to references if you don't want to use that object anymore. However, it is bad practice to count on the GC to collect them at any point soon or at all during your program's execution.
No, it's unnecessary. As soon as heavyObject1 is out of scoped, it'll be marked for GC anyway.
As a general practice, no, because it is not needed.
There are special cases -- I can imagine a long-lived class, for instance, that has a long list of memory consuming objects with which it does something one time and then waits for a period before replacing that list with another list. Might as well null the list while you're waiting, won't hurt anything, and may prevent the program from having to end up with both lists at the same time.
But therein lies the "not needed" principle again. You can't count on the GC to run during particular period, so the program needs to support having both these lists on the heap at the same time, so it doesn't make your program viable if it was not so before.
And let's PLEASE not encourage people to make a 'rule' about it. When I think of all the code I've read where someone puts "final" in front of (nearly) all the variables that (they think) won't change after initialization, making the code less readable and convincing me that the programmer had no understanding of the speed improvement they were supposedly making...
No. It is not generally good practice to null fields or locals.
In most cases the object whose field you are nulling is going to become unreachable before the GC runs. If that happens, the CPU cycles you spent nulling the object's field are going to be wasted.
The only situations where it is necessary / good to null fields / locals are where:
it is likely that the parent object will still be reachable when the GC runs, AND
the child object (graph) is large enough for the amount of memory retained to be significant ... relative to the total heap size.
You might also do it if you are implementing a class that is intended to be used in a wide range of situations ... and some of those situations could fit the criteria above. (For instance, a data structure implementation where the instances could grow large.)
Dereferencing objects is unnecessary unless your class is managing its own memory or your class is caching resources, then obsolete references should be eliminated.
In my application, I would like to load some amount of data into memory when first needed and keep it there in case another part of the application wants to use it. The same data would be accessed from a couple of different Activity'es, but by far not all the user could interact with. So, when not working with the relevant part of my application, I would like Android to feel free to discard the data, reloading them again at need. Note that it is unpredictable for me what the user will do, so I want Android to free the data only if hasn't been used for some time. What is a good approach to doing this?
I thought of creating a class that would be only used statically, loading the data in its static initialisation block. However, I am not sure if Dalvik would ever discard any static data stored this way. I have read something on class loaders but I have no idea what loader is used in loading my class and how it could potentially become discarded. Perhaps someone does...?
Another way I came up with is using weak reference to keep an instance of the data-holding class (non-static, obviously) but here I am afraid that the GC could decide it's useless when no Activity is currently actively operating it, even when memory is no concern at that moment. (In that case, I would like to keep the data loaded.)
The loading of my data is costly. I want, if possible, to destroy it only when the system is running out of memory or when the application exits.
It sounds like SoftReferences are what you need. These are cleared at the garbage collector's discretion when it detects that there is a memory shortfall.
If you read the class javadoc, it gives some hints about how to prevent recently used cache entries from being reclaimed.
For the record, classloaders won't help you manage instances of a class. But making the cache a static should allow the cached objects to be discarded if the cache class gets unloaded.
FOLLOWUP
My data is a solid block that would be represented by a single object.
This rather changes things. If you have a single object to cache, then LRU makes no sense. Basically it sounds like you want to hang onto the object as long as possible ... without trigger OOMEs by hanging onto it too long. This is kind of hard. Indeed, doing a perfect job is going to entail correctly predicting what the user is going to do ... which is clearly impossible.
Possibly the best strategy is to make use of the reference enqueing mechanism, and implement the queue processor to make an "intelligent" choice between letting the object die or recreating the soft link. The "intelligence" might entail looking at how much free memory there is, and / or how long it was since the object was last used. But beware!! If you get this wrong you can cause OOMEs or cause the platform to spend lots of time thrashing the garbage collector.
If I set up the cache to hold 1 object, it would be equivalent to a hard reference, wouldn't it?
Nope. If you use a SoftReference the GC will break the reference if it is running out of memory.
You can use SoftReferences. Take a look at:
http://docs.oracle.com/javase/6/docs/api/java/lang/ref/SoftReference.html
With SoftReferences you can achieve what you need:
" I want, if possible, to destroy it only when the system is running out of memory or when the application exits."
Take a look at
SoftReference gets garbage collected too early
You can also look into LruCache if your looking to cache some data in memory your app.
http://developer.android.com/reference/android/support/v4/util/LruCache.html
For a longer lived disk based cache take a look at Android Objects Cache
You can find the DiskLruCache source at https://github.com/JakeWharton/DiskLruCache/
We all know that the JRE will destroy any object that can no longer be referenced. But is there a way for an object to explicitly destroy itself? Or is that forbidden to avoid the dangling pointer problem?
Naively, I would like to say this = null, but that is disallowed by the compiler (this is probably not a true variable anyway).
Conversely, is there a way for an object to forcibly keep itself alive, by maintaining private copies of this, or otherwise?
No. In fact, you cannot forcibly destroy anything. Even if you have no references to an object, it will continue to exist in memory until the garbage collector decides to run and collect it.
You could keep an object alive by keeping a static reference to it.
Ignoring the academic aspect, you can't ensure an object is physically destroyed in Java (or most any other garbage collected language, like C#). This is because destroying objects is expensive (partly because of the memory compression phase), so the point is to run it as few times as possible.
This said however, you can force an object to release its allocated resources using the disposable pattern, where the object in question exposes a public method to release resources, and you can call it at any time (or it gets called automatically in the finalizer). It requires a bit more bookkeeping, but it gets the job done if really needed.
No you can't destroy an object.
What you could do is have a wrapper object that holds the actual object. If you make sure that nobody else has a reference to that object removing the reference (e.g. by setting it to null) will make the object qualify for the garbage collector. Note that it is still up to the GC to decide when and if to actually collect the garbage.
In order to keep an object alive you need to make sure that there is a reference to it. One way would be to have a static reference from the class of the object. As long as nobody unloads the class your object will stay in memory.
As you said I think it is forbidden to avoid dangling pointer problems. Java memory model is based on Stack and Heap model, if an object destroys itself then what would go to stack (or) other pointers, which references the object?