'. '

StringsUsedInConstantPool

From APIDesign

Revision as of 20:34, 9 March 2009 by JaroslavTulach (Talk | contribs)
(diff) ←Older revision | Current revision (diff) | Newer revision→ (diff)
Jump to: navigation, search

Can one distinguish behaviour of following programs?

private static String msg = new String("Hello World");
public static String sayHello() {
  return msg;
}
private static String msg = "Hello" + " World";
public static String sayHello() {
  return msg;
}

For a while we might consider to use the MemoryAllocations trick, however it is unlikely to work here, as both versions allocate something just once, during the initialization. Also the IdentityCheck is not going to work, as the returned values are always the same. Shall we give up? Well, I did. But one of the participants of HPAPIFest09 showed me following test:

String msg = sayHello();
msg = null;
String hello = new StringBuilder().append("Hel").append("lo").toString().intern();
WeakReference<String> ref = new WeakReference<String>(hello);
hello = null;
assertGC("The string will GC in the first version, but not second, ref);

How this can work? The strings in the constant pool are interned by the Java virtual machine. interned strings are kept in some sort of HashMap and can be garbage collected. But only if nobody has reference to them. Especially if their defining class is unloaded from memory.

The test first loads the API class and its strings into memory. Then it constructs interned string Hello and tries to garbage collected it. In the first case, this succeeds. The first version of the library does not define such string. In the second case the string cannot be garbage collected, as the same interned object is referenced from the API class.

Is this an API? Technically speaking yes. It is externally observable behaviour. Yet it seems to be that for all practical purposes it is useless to treat this as an API. It may be useful in some extreme API fest game, yet I'd rather seen this as forbidden use of API hack.

Personal tools
buy