Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Sponsored Links

Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs

Does an object exist if you can't test its identity?

Can interned Strings be garbage collected?

  • Print
  • Feedback

Page 2 of 2

import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
public class Main
{
    public static void main (String [] args) throws Exception
    {
        URL [] customClassPath = new URL [] {new File (args [0]).toURL ()};
        {
            ClassLoader loader = new URLClassLoader (customClassPath, null);
            Object obj = loader.loadClass ("Main$X").newInstance ();
            
            String s1 = obj.toString ();
            System.out.println (System.identityHashCode (s1));
            s1 = null;
            
            // Release X to GC:
            obj = null;
            loader = null;
        }
        runGC ();
        {
            ClassLoader loader = new URLClassLoader (customClassPath, null);
            Object obj = loader.loadClass ("Main$Y").newInstance ();
            
            String s2 = obj.toString ();
            System.out.println (System.identityHashCode (s2));
        }
    }
        
    public static class X
    {
        public String toString ()
        {
            return "JavaWorld";
        }
        
    } // End of nested class
    
    public static class Y
    {
        public String toString ()
        {
            return "JavaWorld";
        }
        
    } // End of nested class
    ... the rest of Main code as before ...
} // End of class


For the sake of simplicity, I also cheat a little and pass Strings via Object.toString() overrides. When you run this in Sun's 1.4.2 JVM (assume that the bin directory contains your compiled classes), you should see a result similar to this:

>java -cp bin Main bin
26533766
8187137


As you can see, after class X is unloaded, the "JavaWorld" string literal is re-interned by class Y. What appears to be the same global String literal in a program is in fact two different objects at different times during execution—did you know this was possible?

Since Java does not allow conversion of object pointers to other data types, the only way to remember an object's identity is to retain the object pointer itself. If you relinquish this pointer, you give up all rights to know what happens to the object afterwards. Since Java Strings are immutable for most programs, it won't matter if the same String literal is represented by the same String instance at all times or not. But occasionally a curious programmer might figure out what happens under the hood using tricks like System.identityHashCode().

About the author

Vladimir Roubtsov has programmed in a variety of languages for more than 14 years, including Java since 1995. Currently, he develops enterprise software as a senior engineer for Trilogy in Austin, Texas.
  • Print
  • Feedback

Resources