With the following function:
Collection#clear
how can I attempt to reclaim memory that could be freed from an invocation? Code sample:
public class Foo
{
private static Collection<Bar> bars;
public static void main(String[] args){
bars = new ArrayList<Bar>();
for(int i = 0; i < 100000;i++)
{
bars.add(new Bar());
}
bars.clear();
//how to get memory back here
}
}
EDIT
What I am looking for is similar to how ArrayList.remove reclaims memory by copying the new smaller array.
It is more efficient to only reclaim memory when you need to. In this case it is much simpler/faster to let the GC do it asynchronous when there is a need to do. You can give the JVM a hint using System.gc() but this is likely to be slower and complicate your program.
how ArrayList.remove reclaims memory by copying the new smaller array.
It doesn't do this. It never shrinks the array, nor would you need to.
If you really need to make the collection smaller, which I seriously doubt, you can create a new ArrayList which has a copy of the elements you want to keep.
bars= null ;
would be the best. clear doesn't guarantee to release any memory, only to reset the logical contents to "empty".
In fact, bars= null ; doesn't guarantee that memory will be immediately released. However, it would make the object previously pointed by bars and all its dependents "ready for garbage collection" ("finalization", really, but let's keep this simple). If the JVM finds itself needing memory, it will collect these objects (other simplification here: this depends on the exact garbage collection algorithm the JVM is configured to use).
You can't.
At some point after there are no more references to the objects, the GC will collect them for you.
EDIT: To force the ArrayList to release its reference to the giant empty array, call trimToSize()
You can't force memory reclamation, that will happen when garbage collection occurs.
If you use clear() you will clear the references to objects that were contained in the collection. If there are no other references to those objects, then they will be reclaimed next time GC is run.
The collection itself (which just contains references, not the objects referred to), will not be resized. The only way to get back the storage used by the collection is to set the reference bars to null so it will eventually be reclaimed.
Related
I'm reading the Effective Java book and its saying that eliminating obsolete reference is one of best way to avoid memory leaks. according to the below program, by doing -> elements[size] = null; its eliminating obsolete references in that program.
My problem here what is the advantage of doing elements[size] = null;. Any other program can use that freed memory location? Or is it garbage collected?
According to my understanding the array is already allocated the memory for its size. Even we do elements[size] = null; anyone can't use that freed memory location until you do elements = null;. Please someone tell me what is advantage of doing elements[size] = null; here.
public Object pop() {
if (size == 0)
throw new EmptyStackException();
Object result = elements[--size];
elements[size] = null; // Eliminate obsolete reference
return result;
}
My problem here what is the advantage of doing elements[size] = null;.
Here obsolete references refer to object references not required any longer for the program.
You want that unnecessary objects to be free to consume only memory that your program need. Generally it is done for the good working of the current application.
Any other program can use that freed memory location?
Theoretically yes but it also depends on the JVM memory options used. You don't generally focus on it.
elements[size] = null and elements = null; don't have at all the same intention and the same effects.
In the context of the book, elements is a structural intern of a class.
The idea is that some elements of the array may be stale and not required any longer after some removal operations.
The first one (elements[size] = null) will make the object of the array element located at the size index to be eligible to be GC if no other objects reference .
But the second one (elements = null) is much more. It will make all elements of the array to be eligible to be GC if no other objects reference it.
There are two cases we have to distinguish:
The outer object is "teared down" somehow, so it closes any open resource and also "voluntarily" releases all objects it had referred to. This s simply the explicit way of telling the jvm that the corresponding refence is "gone". You make it easier for the gc to understand: the corresponding object is eligible for garbage collection. Of course, that only has that effect if there are no other references to the same object elsewhere. And beyond: doing so isn't really required, the jvm/gc must of course be able to detect any eligible object all by itself.
But nullifying makes sense for refences that exist for longer periods of time, pointing to different objects over that time span. Like a container, such as the stack class in the underlying example. A container must forget about objects it referenced to when they get "removed". Otherwise you create a memory leak!
What happens here?
Let's imagine, elements is a 20-elements Object array (elements = new Object[20];), and has been filled with 18 BigInteger instances, the remaining two places being null.
So the heap now contains 18 BigInteger instances and a 20-elements Object[] array. The garbage collector won't reclaim any of these instances, and that's okay as you'll most probably use them later (via the pop() method).
Now you call the pop() method to get the BigInteger most recently added to the array. Let's assume you just want to print it and then forget it, so in your overall application that number isn't needed any more, and you'd expect the garbage collector to reclaim it. But that won't happen unless you do the null assignment
elements[size] = null; // Eliminate obsolete reference
Why that?
As long as you store the reference to an object in some accessible place, the garbage collector believes that you'll still need the object later.
As long as elements[17] still refers to the BigInteger, it can potentially be accessed by your program, so it can't be reclaimed. If elements[17] points to null, the BigInteger that used to be there isn't accessible via elements any more and can be reclaimed by the garbage collector (if no other part of your code still uses it).
Conclusion
It's only worth thinking about "obsolete references" if you have a long-living storage structure that contains fat objects, and you can tell at some point in time that you won't need one of the stored objects any more. As you won't need this object any more, you can now re-assign the storage with null, and then the GC no longer believes you still need the object and is able to reclaim the storage space.
Backstory
In a library that I maintain we have an internal map keeping track of our cache.
Users of the library are interested in having list access to this map, however we can only provide this by copying its contents (thread-safety reasons).
The idea is to cache this list when it is first accessed without having much memory overhead on a second access.
To illustrate:
List<Bob> list = cache.asList();
List<Bob> otherList = cache.asList(); // use from cache, if still available
The problem is, we don't want to keep this list forever if its not needed anymore. Since java uses GC we thought it would be appropriate to use a WeakReference for this, to allow using it if its not collected.
Question
If I have a WeakReference<List<Bob>> stored inside my class, what happens if one of the elements becomes weakly reachable (which implies the list is weakly reachable)? Is it possible that the GC decides to just collect the element inside the list or would it look for all other weakly reachable objects referencing it and also collect them, in this case the list?
The problem would be, if the GC collected an element of the list and we then try to access the list again (if thats even possible) what would happen?
Clarifications
I'm not interested in the reachability of the list, I know that the list is inside the WeakReference and that the elements are irrelevant to its reachability. I care about a specific state, in which both the list and an element of the list are weakly reachable and whether it is possible that the GC only collects the element but not the list itself. What exactly does the GC do in this specific scenario?
As long as the List itself is not weakly reachable its elements will not be either. (Assuming the list implementation itself does not use weak references or similar)
So there is no problem with having the list cached with a weak reference because it would either be garbage collected completely or not at all.
In provided case (WeakReference<List<Something>>) you have only such possible scenario:
public class Test {
private WeakReference<List<String>> listWeakReference;
public Test(final WeakReference<List<String>> listWeakReference) {
this.listWeakReference = listWeakReference;
}
public static void main(String[] args) {
List<String> testList = Arrays.asList("a", "b", "c");
Test test = new Test(new WeakReference<>(testList));
// Initial check
System.out.println(test.listWeakReference.get());
// Call gc and check
System.gc();
System.out.println(test.listWeakReference.get());
// Remove reference and call gc
testList = null;
System.gc();
System.out.println(test.listWeakReference.get());
}
}
Firstly SoftReference is better for caches, and even that isn't very good.
WeakReference may be released immediately the reference becomes weakly reachable. However, it might not do that until sometime into execution - i.e. it doesn't happen during extensive testing, but it does in production. Fun times. NetBeans used to do this in its caching of files. Of course the rest of the code was expecting the caching so grabbed and released references with incredible frequency. After sometime using the application it would suddenly hammer file I/O and become unusable.
For best performance you need to explicitly estimate how much memory the process is using and release as necessary. Not easy.
Back to the question. Collection of contents of WeakReference (and SoftReference is a two phase operation. The first phase just clears the Reference (and queues if you are using that). The associated memory is not collected. The memory may be resurrected through a finaliser. The WeakReference is forever cleared and queued, it does not reset. Only when an object is completely unreachable can the associated memory be collected as a separate phase.
Fear not, Java is memory-safe (bugs excepted).
I have to assume that the following method doesn't leak memory:
public final void setData(final Integer p_iData)
{
data = p_iData;
}
Where data is a property of some class.
Every time the method gets called, a new Integer is replacing the currently existing data reference. So what's happening with the current/old data?
Java has to be doing something under the hood; otherwise we'd have to null-out any objects every time an object is assigned.
Simplistic explanation:
Periodically the garbage collector looks at all the objects in the system, and sees which aren't reachable any more from live references. It frees any objects which are no longer reachable.
Note that your method does not create a new Integer object at all. A reference to the same Integer object could be passed in time and time again, for example.
The reality of garbage collection is a lot more complicated than this:
Modern GCs tend to be generational, assuming that most objects are short-lived, so it doesn't need to check the whole (possibly large) heap as often; it can just check "recent" objects for liveness frequently
Objects can have finalizers - code to be run before they're garbage collected. This delays garbage collection of such objects by a cycle, and the object could even "resurrect" itself by making itself reachable
Modern GCs can collect in parallel, and have numerous tweaking options
Java is a garbage-collected language.
Once there are no more live references to an object, it becomes eligible for garbage collection. The collector runs from time to time and will reclaim the object's memory.
In a nutshell, your code is 100% correct and is not leaking memory.
It gets garbage collected eventually.
if there is no ther reference to data, the garbage collector of java will clean the old data up and free the memory
Actually, since Integer is an object not a primitive type, the line:
data = p_iData;
is updating a reference.
Now, the old object that this.data used to point to will be examined by the GC to determine if there are no more references to that object. If not, that object is destroyed and the memory is freed (at some later time)
If the object previously referenced by data is no longer referenced by any object structure that is referenced from any running thread it is eligible for garbage collecion. GC is performed by Java in the background to free the memory of unused objects.
i want to show one example to you
in some code :
int x;
x=10;
x=20;
initially i assigned x to 10
again x to 20
first reference memory will be handled by Java GC.
Java GC is a thread tht run continuously and checked unreferenced memory and clean it .
I'm running a java program that uses many vectors. I'm afraid my use of them is causing the garbage collector not to work.
I have many threads that do:
vec.addAll(<collection>);
and other threads that do:
vec.remove(0);
I have printouts that show the vector is empty from time to time but I was wondering if the memory is actually freed.
Do I need to worry?
If the objects in your Vectors are not referenced anywhere (by the Vector or by any other code), then they will get collected at the garbage collector's discretion. 99.999% of the time the garbage collector won't need your help with this.
However, even after the garbage collector frees the objects, it may not give heap memory back to the operating system, so your process may appear to hold more memory than it should.
Additionally, I'm very not familiar with the implementation of the Vector class (as others have pointed out, you should really be using ArrayList instead), but when you call .remove() I don't think the underlying array is ever resized downward. So if you stuff several thousand objects into a Vector and then delete them all, it will probably still have several thousand bytes of empty array allocated. The solution in this case is to call vector.trimToSize().
The memory will eventually be freed if there are no references to the objects in question. Seeing your vectors become empty indicates that at least they are not holding on to references. If there is nothing else with references to those objects, they will be cleaned up, but only when the garbage collector chooses to do so (which is always before you run out of memory).
(Caveat: Obviously calling remove(0) will only remove the first element from the Vector, not multiple elements.)
Assuming your Vector is empty then you do not need to worry about garbage collection if the objects in your vector are not being referenced elsewhere. However, if there are still other references to the objects then there is no way they can be garbage collected.
To verify this, I'd recommend running a profiler (e.g. JProfiler) and periodically "snapping" the object count for the type of object being stored in your Vector, and then monitor this count to see if it increased over time.
One other piece of advice: Vector is obsolete; You should consider using LinkedList or ArrayList instead, which are thread-unsafe equivalents. If you wish to make them thread-safe you should initialise them using Collections.synchronizedList(new ArrayList());
No, you don't. If the vector is empty it is not referencing objects you once put in there. If you want to know what is holding on to memory, you can get a profiler and look at what is consuming the memory.
No.
Just trust the implementors of the standard library. They probably have done a good job.
If you really worry about memory leaks, call this from time to time :
System.out.println("Total Memory"+Runtime.getRuntime().totalMemory());
System.out.println("Free Memory"+Runtime.getRuntime().freeMemory());
The implementation of java.util.Vector.remove(int) from JDK 1.6 is:
public synchronized E remove(int index) {
modCount++;
if (index >= elementCount)
throw new ArrayIndexOutOfBoundsException(index);
Object oldValue = elementData[index];
int numMoved = elementCount - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index, numMoved);
elementData[--elementCount] = null; // Let gc do its work
return (E)oldValue;
}
As you can see, if elements are removed from the vector, the vector will not keep a reference to to them, and hence not impede their garbage collection.
However, the vector itself (and the potentially large array backing it) might not be reclaimed.
I heard most elegant property of java is Garbage Collection
I wanna know does it guarantee that a program will not run out of memory?
No, it's always possible that you'll try to allocate more memory than is available.
Automatic garbage collection only means that garbage (i.e., unreferenced memory) is automatically collected (i.e., reclaimed for further use). If you keep references to it, it's not garbage, and not collected.
No it does not guarantee this. It is perfectly possible for a programmer to mistakingly create objects which never go out of scope, thus consuming more and more memory until all heap is exhausted.
It is the programmer's responsibility to ensure that objects no longer in use are no longer referenced by the application. That way the garbage collector can do its job and reclaim memory used by these objects.
Example
public class Main {
public static void main(String[] main) {
List<String> l = new LinkedList<String>();
// Enter infinite loop which will add a String to
// the list: l on each iteration.
do {
l.add(new String("Hello, World"));
} while(true);
}
}
No, there are still many ways to run out of memory. The garbage collector can only reclaim memory for objects that are no longer referenced - it is up to you to make sure that you are not referencing objects you don't need, or to use Soft References for objects you would like to have, but don't mind disappearing if memory gets tight.
To answer your question, NO. Garbage collection does not guarantee that a program will not run out of memory.
Consider object you don't want to
use any more are like garbage.
References to those objects will be
like having that garbage in your
house.
Garbage collection is like your
town's garbage truck that collects
garbage.
If you won't release those
references, it is like not taking
garbage out and soon your house will
be over filled with garbage as
garbage truck guys won't take out
garbage from your house.
Unreferenced objects will be garbage collected automatically by garbage collector. In java, most references to objects are released automatically once you come out of method.
Objects have reference to other objects, which in turn referr to other objects creating whole object graph. So as such object can be referenced by more than one object.
If object is having zero references,
it is eligible for garbage
collection.
Objects are allocated on heap.
Garbage collector runs from time to
time to delete unreferenced objects
from heap.
If you keep creating more objects on
heap without releasing you will
eventually get OutOfMemoryError
Example with garbage collection at work
public class TestGarbageNoError {
public static void main(String[] args) {
String hugeString;
for (int i = 0; i < Integer.MAX_VALUE; i++) {
System.out.println("i = " + i);
hugeString = getHugeString();
// At each iteration reference variable hugeString
// points to new String object. Hence there will be
// zero reference to previous string object and will
// eventually be garbage collected
}
}
public static String getHugeString() {
StringBuilder sb = new StringBuilder();
for (int x = 0; x < 5000000; x++) {
sb.append(x);
}
return sb.toString();
}
}
.
Example with memory leak at work
public class TestGarbageError {
public static void main(String[] args) {
Collection<String> memoryLeak = new ArrayList<String>();
for (int i = 0; i < Integer.MAX_VALUE; i++) {
System.out.println("i = " + i);
String hugeString = getHugeString();
memoryLeak.add(hugeString);
// At each iteration reference variable hugeString
// points to new String object. But all objects are added
// to memoryLeak Collection and will always have atleast one
// reference, i.e. from memoryLeak object. Hence this string
// objects will never be garbage collected and program will
// eventually run out of memory
}
}
public static String getHugeString() {
StringBuilder sb = new StringBuilder();
for (int x = 0; x < 5000000; x++) {
sb.append(x);
}
return sb.toString();
}
}
No. If you construct a lot of objects (millions) and keep a reference to them so they don't go out of scope (for example by adding them to an ArrayList), you could run out of addressable memory.
Absolutely not. Even in a garbage collected language like Java you can easily lose references, meaning objects will never get garbage collected.
Even then, you may simply instantiate (and keep reference to) too many objects for the system to handle.
How could anything ensure a program doesn't run out of memory short of arbitrarily deleting an item from memory to make room for new allocations?
Now, what if you are actually keeping a reference on (using) the thing randomly chosen to be evicted? You will soon have incorrect behavior.
No. The garbage collector, helps you to free unused memory automatically.
The way it works is, if an object reference can't be reached, the memory for that object may be garbage collected.
For instance:
public void test() {
Object o = new Object();
// the memory used by o may be garbage collected after this line
}
But if you never release object references, the garbage collector will never collect anything and a OutOfMemoryError will be thrown.
List list = ....
public void test() {
o = new Object();
list.add( o );
// the memory used by o WON'T be garbage collected after this line
// because its reference is used in the list.
}
If you use this several times:
while( true ) {
test();
}
The list will keep growing indefinitely until you run out of memory
No. Garbage collection only protects against one kind of memory leak. Specifically, the kind that occurs if you don't explicitly free up memory when your application no longer needs it. If your application holds references to unneeded objects (eg. evergrowing Lists), the garbage collector cannot clean them up and your application can still run out of memory.
No, not at all.
In languages without garbage collection, the programmer (or a library he uses) is responsible for making requests for memory and for returning the allocated memory for "recycling". there are no guarantees that the memory would be available when it is requested. However, if you never explicitly "recycle", there could be a situation where a request is rejected because no memory is available, but that if the memory was recycled that block could have been returned for this request.
Having automated garbage collection means that the system may recycle for you. As a result, certain requests would be filled using "recycled" memory. However, as with non-GC languages, some requests cannot be filled.
For instance, if your system has 1000 blocks available and you need 1500 at the same time, no GC in the world is going to help you because nothing is really available for recycling.
No, garbage collection cannot guarantee that your application will not run out of memory. It will not even guarantee that your application will not run out of memory when memory is available. If you come close to running out of memory or are allocating many object it can cause GC to thrash, throwing an out of memory exception. The program can also run out of memory when it has used all the physical memory (actual and virtual) or the program exceeds the maximum memory allowed by the JVM (see -Xmx).
However, it is guaranteed that before the JVM declares OutofMemoryException it will garbage collect all collectible references and consider to use the now free memory.