Thursday, May 21, 2009

"My Location" feature on Non GPS-Enabled devices

These days I often use the routing and "Get Directions" of Google Maps on my Window Mobile. And Yes, It works in India too to a great extent. One feature that always surprises me is "My Location" - Auto-detecting my geographic location. Simply because my mobile does no have a GPS receiver.

So how does Google find out my location to a precision of 500 metres (sometimes 5KM when I go for a drive outside the city)? When I used to talk to people about this the unanimous answer was "Google finds it from your mobile signal".
I too was under the assumption that Google Maps, through your handset asks your mobile phone operator the geographical co-ordinates of the tower from where it's catching the signal. Simple huh? But not.

On reading I found out that the Mobile operator does not say anything about the location coordinates of your cell tower or your device. Google does a trick here.
Each mobile coverage cellular area (remember the Hexagon shaped cell) has a number attached to it (Some kind of serial number to uniquely identify that hexagon shaped cell). Google then uses a database that maps this cell number to geographical coordinates.

But how does Google get the coordinates that fall under that cell?

To do that, Google uses other GPS-enabled devices that are active in your cell area. It collects data like geographical location and service cell ID from these anonymous devices. At the end what Google has is an expanding database of service cell ID (Vs) set of coordinates that fall under that cell.

So that's how the "My Location" in a Non-GPS enabled device is a bigger circle and Google says its your location approximated to some specific metres. It also explains why Google does not show it at all at some remote places when I travel on the highway outside the city. Looks like nobody has gone there and activated their GPS reciever and "helped" Google :-D

Monday, February 16, 2009

Browser - The new desktop?

Everyday as I use Google talk, I wonder "Why are they not coming up with a new version? It's been almost two years now and every month they add something new to the web based talk." Be it invisible mode, conference chat, video chat or even emoticons - the web gadget has it all.

Whenever I read about a new feature in the web version, I make up my mind to start using the talk gadget or Gmail chat. I login through the gadget, start chatting with people, in parallel do my work, and at some point when I do an alt+tab to bring the browser to focus, I see my friends irritated - I have not seen their messages for the past 30 minutes :-(
Yes, those notifications are something I miss the most in the web version. If you minimize the browser, while a different tab was on focus, you would not be able to see the blinking Google talk tab, when someone messages you.
For me, when it comes to an instant messenggers, the usability is much higher when it sits on the desktop.

And the need to use Google talk - All my friends have moved to it. Otherwise I still prefer Yahoo! Messenger. Thank God I am not a Linux user - they don't even have the desktop version on Linux. Sigh.

After seeing Google Chrome, my doubts of Google never again releasing a new desktop GTalk version has gone up steeply. The new home page, the new tab page, the very idea of application shortcuts, the browser task manager etc. look a lot like Google's attempt to make the browser the new home of the PC.

Does Google consider browser to be the next desktop? Sometimes it looks like; but remember - Microsoft Sells and would continue to.

Thursday, June 26, 2008

The Interesting Leak - Now at Javalobby

My last two posts have been published as an article at Javalobby.
Link: http://java.dzone.com/articles/the-interesting-leak

Sunday, June 22, 2008

The leak continues..

This again is a follow up of my previous post - The Interesting Leak.
I was quite amused after reading Markus' follow-up post An interesting leak when using WeakHashMaps.
What surprised me most was If you put
("abc" + "def").intern();
as key in the WeakHashMap, it doesn't get GC'd whereas
(new String("abc") + "def").intern()
as key leads to the entry being garbage collected.
Huh!
Tried all combinations. No clarity. Last resort - Pinged Rajiv.
And so went the conversation -

Me : If you put ("abc" + "def").intern(); as key, it doesnt get GC'd but if you put (new String("abc") + "def").intern() it gets GC'd
Rajiv : Decompile and see if "abc"+"def" is being converted to "abcdef" by javac
Me: Yes it is. So?
[This could be the clue. Am still thinking.. tick tick tick]

Rajiv: Check if "abcdef"== (new String("abc") + "def").intern()
Me: It is... printed the identitity hashcodes.
Rajiv: In the class you have both "abcdef" and (new String("abc") + "def").intern() and still
(new String("abc") + "def").intern() gets gc'ed?
Me: God! Then it doesn't get gc'd.
[Now Rajiv cracks it -]

Rajiv: "I think intern is weak map and constant pool has a strong ref"
Me: ohh!
Me: In that case (new String("abc") ).intern(); should get GC'd right? But we saw it doesn't. The maya happens only when someString is '+'d to (new String("abc")) and then the resultant String is interned.
Me: Just (new String("abc")).intern() doesnt get GC'd.
Rajiv: When you say (new String("abc")).intern() there is a string "abc" in constant pool.
Me: Yes "abc" in constant pool would be the literal we created and passed as argument to the String constructor.
Rajiv: (new String("abc")).intern() returns that string. So wont get gc'ed
Me: Oh yeah. Got it!
Me: So only when you do a "+" you get a String which is not there in constant pool and hence it gets GC'd ...
Rajiv: ya right.

I had earlier thought of intern pool and constant pool to be the same. But Rajiv 's prediction of intern being a weak map and constant pool holding a strong ref looks quite convincing.
Oo la.. That solved our mystery. Thanks Rajiv:-)

Wednesday, June 4, 2008

The interesting leak

This again is one of those interesting observations I ran into during some memory optimizations CXF. Coincidently here also its a WeakHashMap.
Consider the code snippet below.
public class TestWeakHashMap
{
private String str1 = new String("newString1");
private String str2 = "literalString2";
private String str3 = "literalString3";
private String str4 = new String("newString4");
private Map map = new WeakHashMap();

private void testGC() throws IOException
{
map.put(str1, new Object());
map.put(str2, new Object());
map.put(str3, new Object());
map.put(str4, new Object());

/**
* Discard the strong reference to all the keys
*/
str1 = null;
str2 = null;
str3 = null;
str4 = null;

while (true) {
System.gc();
/**
* Verify Full GC with the -verbose:gc option
* We expect the map to be emptied as the strong references to
* all the keys are discarded.
*/
System.out.println("map.size(); = " + map.size() + " " + map);
}
}
}
What do we expect the size of the map to be after full GC? I initially thought it should be empty. But it turned out to be 2.

Look at the way the four Strings are initialized. Two of them are defined using the 'new' operator, whereas the other two are defined as literals. The Strings defined using the 'new' operator would be allocated in the Java heap, but the Strings defined defined as literals would be in the literal pool.
The Strings allocated in the literal pool (Perm Space) would never be garbage collected.
This would mean that String 'str2' and 'str3' would always be strongly referenced and the corresponding entry would never be removed from the WeakHashMap.

So next time you create a 'new String()' , put it as a key in a WeakHashMap, and later intern() the String, beware - Your key will always be strongly referenced. [Invoking intern() method on a String will add your String to the literal pool if some other String equal to this String does not exist in the pool]

Tuesday, June 3, 2008

Some more play with WeakHashMap

Last couple of days, I ran into some interesting observations while doing some memory optimizations CXF.
Consider the below snippet.



import java.util.Map;
import java.util.WeakHashMap;

public class TestWeakHeakHashMap
{
private String name = new String("java");
private Map cache = new WeakHashMap<String, ComplexDO>();

public void testMethod()
{
cache.put(name, new ComplexDO("1", name));

//Discard the strong reference to the key
name = null;
while (true) {
System.gc();
/**
* Verify Full GC with the -verbose:gc option
Since there is no strong reference to the key, it is assumed that the
entry has been removed from the WeakHashMap
*/
System.out.println(cache.size());
}
}

private class ComplexDO
{
private String id;
private String name;

public ComplexDO(String id, String name)
{
this.id = id;
this.name = name;
}
}
}



Now when the testMethod() is run what do you expect the output to be? Since the strong reference to key is discarded, we assume that the entry from the map would be removed, and map would be empty after a full GC.
But that does not happen though.

Let us see what was the put operation on the WeakHashMap.

cache.put(name, new ComplexDO("1", name));
Here the value ComplexDO was holding the key name. This would mean that the value always strongly refers to the key, and hence the key would never be garbage collected. The entry would always remain the map.

This is what WeakHashMap API says -
"The value objects in a WeakHashMap are held by ordinary strong references. Thus care should be taken to ensure that value objects do not strongly refer to their own keys, either directly or indirectly, since that will prevent the keys from being discarded."

Monday, June 2, 2008

WeakHashMap : An Observation

Consider the following code snippet.

1 public class TestWeakHashMap {
2 public static void main(String[] args) {
3 WeakHashMap map=new WeakHashMap();

4 String s1=new String("java");
5 map.put(s1, "good");

6 String s2=new String("java");
7 map.put(s2,"ok");

//Since s1.equals(s2) is true and hash is same, the earlier value
//against key s1 ("good") in the map is replaced by the new one. ("ok")

8 s1=null;

9 System.gc();
//Verify Full GC with the -verbose:gc option

10 System.out.println(map.size());
11 }
12 }

What do we expect the output to be? 1? No, Not exactly.

Here s1 and s2 are two different objects on the heap. So in line 5, a new (key,value) pair with key s1 is put into the map. Later when a (key,value) with key s2 is being put into the map, it checks for equals on s1 and s2 and their hashcode. When it finds the equals returns true and hashcde is same, it replaces the value of the earlier entry with the new value. But the issue(?) here is, WeakHashMap/HashMap does not replace the earlier key while adding a (key, value) pair whose key is actually a duplicate key in the map.
So even after putting an entry with key s2, the WeakHashMap has only one entry whose key refers to the object refered by s1 and not s2.
Now the object on the heap refered by s1, has one strong reference(through s1) and one weak reference through the WeakHashMap.
Later when I say s1=null, the object on the heap refered to by s1 lost the strong reference and when gc happens, the entry is removed from the map.

So thats how it works.

Also note WeakHashMap is only a wrapper over HashMap and the HashMap's put api says " If the map previously contained a mapping for this key, the old value is replaced by the specified value."

So just be careful when you use WeakHashMap and your usage scenario is similar to the above.

Moved from JRoller

http://jroller.com/page/bharath