I am working on querying the address book via J2ME and returning a custom
Hashtable which I will call pimList. The keys in pimList {firstname, lastname} maps to an object (we'll call this object ContactInfo) holding (key, value) pairs e.g. work1 -> 44232454545, home1 -> 44876887787
Next I take firstName and add it into a tree.
The nodes of the tree contains the characters from the firstName.
e.g. "Tom" would create a tree with nodes:
"T"->"o"->"m"-> ContactInfo{ "work1" -> "44232454545", "home1" -> "44876887787" }
So the child of the last character m points to the same object instance in pimList.
As I understand it, the purpose of WeakReferences is to that its pointer is weak and the object it points to can be easily GC'ed. In a memory constraint device like mobile phones, I would like to ensure I don't leak or waste memory. Thus, is it appropriate for me to make:
pimList's values to be a WeakReference
The child of node "m" to point to WeakReference
?
It should work. You will need to handle the case where you are using the returned Hashtable and the items are collected however... which might mean you want to rethink the whole thing.
If the Hashtable is short lived then there likely isn't a need for the weak references.
You can remove the items out of the Hashtable when you are done with them if you want them to be possibly cleaned up while the rest of the Hashtable is stll being used.
Not sure I exactly understood what you try to do but an objects reachability is determined by the strongest reference to it (hard reference is stronger than soft reference which is stronger than weak reference which is stronger than phantom reference).
Hard referenced objects won't be garbage collected. Soft referenced objects will be garbage collected only if JVM runs out of memory, weak referenced objects will be garbage collected as soon as possible (this is theory it depends on the JVM and GC implementation).
So usually you use softreference to build a cache (you want to reference information as long as possible). You use weakreference to associate information to an object that is hard referenced somewhere, so if the hardreferenced object is no longer referenced the associated information can be garbage collected - use weakhashmap for that.
hope this helps...
I am not sure if the WeakMap is the right thing here. If you do not hold strong references anywhere in your application, the data in the map will disappear nearly immediately, because nobody is referencing it.
A weak map is a nice thing, if you want to find things again, that are still in use elsewhere and you only want to have one instance of it.
But I might not get your data setup right... to be honest.
Related
Do I have to .clear() HashSet and HashMap everytime, when variable is no longer used?
I have a lot of temporary variables in methods in my application that are HashSets and HashMaps. Do I have to clear them everytime when, for example, method is done? Will GC remove it automaticly if object will not be longer used by something?
I am asking because a lot of people point that I have to clear data in any hashmap if program is done and data stored in hashmap will not longer be used.
When the hashmap goes out of scope, it would be automatically garbage collected, so you shouldnt need to call clear if all you are doing is letting to getting removed.
Clear is good for if you want to re-use the map but want to empty it of all data.
GC Will clear it for you when there's a lack of memory .. but it's better to set your references that you won't use anymore to null
HashMap and HashSet are objects in java. So when an object is no longer referred and is out of reach it would become eligible for Garbage Collection.
However, if you think there is a memory leakage then I recommend to explicitly set all the Object references of the related HashMap and HashSet to null immediately after you don't need them.
You can refer to memory leakage here:
https://dzone.com/articles/memory-leak-andjava-code
If you are not sure about memory leakage, for the safe side you can set the references of the objects to null.
I have a map that I use to store dynamic data that are discarded as soon as they are created (i.e. used; they are consumed quickly). It responds to user interaction in the sense that when user clicks a button the map is filled and then the data is used to do some work and then the map is no longer needed.
So my question is what's a better approach for emptying the map? should I set it to null each time or should I call clear()? I know clear is linear in time. But I don't know how to compare that cost with that of creating the map each time. The size of the map is not constant, thought it may run from n to 3n elements between creations.
If a map is not referenced from other objects where it may be hard to set a new one, simply null-ing out an old map and starting from scratch is probably lighter-weight than calling a clear(), because no linear-time cleanup needs to happen. With the garbage collection costs being tiny on modern systems, there is a good chance that you would save some CPU cycles this way. You can avoid resizing the map multiple times by specifying the initial capacity.
One situation where clear() is preferred would be when the map object is shared among multiple objects in your system. For example, if you create a map, give it to several objects, and then keep some shared information in it, setting the map to a new one in all these objects may require keeping references to objects that have the map. In situations like that it's easier to keep calling clear() on the same shared map object.
Well, it depends on how much memory you can throw at it. If you have a lot, then it doesn't matter. However, setting the map itself to null means that you have freed up the garbage collector - if only the map has references to the instances inside of it, the garbage collector can collect not only the map but also any instances inside of it. Clear does empty the map but it has to iterate over everything in the map to set each reference to null, and this takes place during your execution time that you can control - the garbage collector essentially has to do this work anyways, so let it do its thing. Just note that setting it to null doesn't let you reuse it. A typical pattern to reuse a map variable may be:
Map<String, String> whatever = new HashMap<String, String();
// .. do something with map
whatever = new HashMap<String, String>();
This allows you to reuse the variable without setting it to null at all, you silently discard the reference to the old map. This is atrocious practice in non-memory managed applications since they must reference the old pointer to clear it (this is a dangling pointer in other langauges), but in Java since nothing references this the GC marks it as eligible for collection.
I feel nulling the existing map is more cheaper than clear(). As creation of object is very cheap in modern JVMs.
Short answer: use Collection.clear() unless it is too complicated to keep the collection arround.
Detailed answer: In Java, the allocation of memory is almost instantaneous. It is litle more than a pointer that gets moved inside the VM. However, the initialization of those objects might add up to something significant. Also, all objects that use an internal buffer are sensible to resizing and copying of their content. Using clear() make sure that buffers eventually stabilize to some dimension, so that reallocation of memory and copying if old buffer to new buffer will never be necessary.
Another important issue is that reallocating then releasing a lot of objects will require more frequent execution of the Garbage collector, which might cause suddenly lag.
If you always holds the map, it will be prompted to the old generation. If each user has one corresponding map, the number of map in the old generation is proportionate to the number of the user. It may trigger Full GC more frequently when the number of users increase.
You can use both with similar results.
One prior answer notes that clear is expected to take constant time in a mature map implementation. Without checking the source code of the likes of HashMap, TreeMap, ConcurrentHashMap, I would expect their clear method to take constant time, plus amortized garbage collection costs.
Another poster notes that a shared map cannot be nulled. Well, it can if you want it, but you do it by using a proxy object which encapsulates a proper map and nulls it out when needed. Of course, you'd have to implement the proxy map class yourself.
Map<Foo, Bar> myMap = new ProxyMap<Foo, Bar>();
// Internally, the above object holds a reference to a proper map,
// for example, a hash map. Furthermore, this delegates all calls
// to the underlying map. A true proxy.
myMap.clear();
// The clear method simply reinitializes the underlying map.
Unless you did something like the above, clear and nulling out are equivalent in the ways that matter, but I think it's more mature to assume your map, even if not currently shared, may become shared at a later time due to forces you can't foresee.
There is another reason to clear instead of nulling out, even if the map is not shared. Your map may be instantiated by an external client, like a factory, so if you clear your map by nulling it out, you might end up coupling yourself to the factory unnecessarily. Why should the object that clears the map have to know that you instantiate your maps using Guava's Maps.newHashMap() with God knows what parameters? Even if this is not a realistic concern in your project, it still pays off to align yourself to mature practices.
For the above reasons, and all else being equal, I would vote for clear.
HTH.
Why are Java weak references not counted as references with respect to garbage collection?
Because that is simply its purpose.
An object is garbage collected if 0 references are pointing at it. Since a weak reference should not, on its own, prevent an object from being garbage collected, it is not counted during GC.
Have a look at the various definitions of Reachability to get a clear picture:
Package java.lang.ref Description: Reachability
Weak references are not counted as references under GC because that is the whole point of their existence and their definition: references that do not cause the object they point to to be considered live.
This is very useful because it lets you maintain relationships among objects which automatically go away when you are no longer interested in those objects.
You can extend objects with properties, without causing objects to become permanently linked into the reachability graph (turning into "semantic garbage" when no longer needed).
For example, a global weak hash table could let you find all of the Student objects belonging to a given Course and vice versa: all the Course objects belonging to a Student.
If a Student becomes garbage (you lose all your references to it), the weak hash table will automatically remove the entry associating that Student with its Course objects.
The advantage is that you didn't have to add a list of students into the Course class. And also, when you want to get rid of a Student, you do not have to hunt down every Course object and remove that student from its list.
Just lose track of the Student "naturally" and the weak hash table will purge itself.
When a entry in a map has weak key reference, the entry will be removed at the next garbage collection, right?
I can understand that the MapMaker class provides the weakKeys method. But I am confused with the weakValue(). when should I use weakValue or softValue in MapMaker?
You'd use weakValues() when you want entries whose values are weakly reachable to be garbage collected. For an example of when this might be useful... say you have a class that allows users to add objects to it and stores them as values in a Map for whatever reason. This class is typically used as a singleton, so it'll stick around the whole time your application is running. However, the objects the user adds to it aren't necessarily so long-lived. The application will be done with them long before it finishes. You don't want the user to have to manually remove these objects from your class when it is finished with them, but you don't want a memory leak by keeping references to them in your class forever (in other words garbage collection should just work like normal, ignoring your class). The solution is to give the map weakValues() and everything will work as you want.
softValues() is good for caching... if you have a Map<Integer, Foo> and you want entries to to be removable in response to memory demand, you'd want to use it. You wouldn't want to use weakKeys() or softKeys() because they both use == identity, which would cause problems for you (wouldn't be able to get a value with key 300 out because the key you pass in probably wouldn't == the key in the map).
Suppose I have a doubly linked list. I create it as such:
MyList list = new MyList();
Then I add some nodes, use it and afterwards decide to throw away the old list like this:
list = new MyList();
Since I just created a new list, the nodes inside the old memory area are still pointing to each other. Does that mean the region with the old nodes won't get garbage collected? Do I need to make each node point to null so they're GC'd?
No, you don't. The Java GC handles cyclic references just fine.
Conceptually, each time the GC runs, it looks at all the "live" root references in the system:
Local variables in every stack frame
"this" references in every instance method stack frame
Effectively, all static variables (In fact these are really referenced by Class objects, which are in turn referenced by ClassLoaders, but lets ignore that for the moment.)
With those "known live" objects, it examines the fields within them, adding to the list. It recurses down into those referenced objects, and so on, until it's found every live object in the system. It then garbage collects everything that it hasn't deemed to be live.
Your cyclically referenced nodes refer to each other, but no live object refers to them, so they're eligible for garbage collection.
Note that this is a grossly simplified summary of how a garbage collector conceptually works. In reality they're hugely complicated, with generations, compaction, concurrency issues and the like.
If you created your own double linked list, and you put in this double linked list Containers (that contain items from your list); only those containers are linked one to another.
So in your list you'll have an object A contained in A'. A' is linked to B' and B' is a container that hold B etc. And none of the object have to reference another.
In a normal case those containers won't be available from outside (only the content is interesting); so only your list will have references to your containers (remember that your content isn't aware of his container).
If you remove your last reference to your list (the list, not the container nor the content) the GC will try to collect your list content, witch is your containers and your contents.
Since your containers are not available outside the only reference they have is one each other and the main list. All of that is called an island of isolation. Concerning the content, if they still have references in your application, they will survive the GC, if not they won't.
So when you remove your list only A' and B' will be deleted because even if they still have references, those references are part of an island. If A and B have no more references they will be deleted too.
No -- Java (at least as normally implemented) doesn't use reference counting, it uses a real garbage collector. That means (in essence) when it runs out of memory, it looks at the pointers on the stack, in registers, and other places that are always accessible, and "chases" them to find everything that's accessible from them.
Pointers within other data structures like your doubly-linked list simply don't matter unless there's some outside pointer (that is accessible) that leads to them.
No, the GC will reclaim them anyways so you don't need to point them to null. Here's a good one paragraph description from this JavaWorld article:
Any garbage collection algorithm must
do two basic things. First, it must
detect garbage objects. Second, it
must reclaim the heap space used by
the garbage objects and make it
available to the program. Garbage
detection is ordinarily accomplished
by defining a set of roots and
determining reachability from the
roots. An object is reachable if there
is some path of references from the
roots by which the executing program
can access the object. The roots are
always accessible to the program. Any
objects that are reachable from the
roots are considered live. Objects
that are not reachable are considered
garbage, because they can no longer
affect the future course of program
execution.
The garbage collector looks if objects are referenced by live threads. If objects are not reachable by any live threads, they are eligible for garbage collection.
It doesn't matter if the objects are referencing each other.
As others have pointed out, the Java garbage collector doesn't simply look at reference counting; instead it essentially looks at a graph where the nodes are the objects that currently exist and links are a reference from one object to another. It starts from a node that is known to be live (the main method, for instance) and then garbage collects anything that can't be reached.
The Wikipedia article on garbage collection discusses a variety of ways that this can be done, although I don't know exactly which method is used by any of the JVM implementations.
The garbage collector looks for objects that isn't referenced anywhere.
So if you create a object and you loose the reference like the example the garbage collector will collect this.