6 Replies Latest reply on Dec 13, 2013 12:07 PM by EJP

    Why is my weak reference returning null?  Turing award for an answer :P

    1059726

      From the code posted below.  In the main method, the first println, it will print "x" object.  However, the object passed in the second println is an rval object and it *consistently* returns null.  Note, I've tried switching the two print's around and it the result is unchanged.  I guess I was under the opinion that explicit binding to x' and being on the stack as a temporary variable would be considered strong and *both* should return the object passed to the "method" method.  But yet, it gets lost in one instance.  I was also thinking that "method"'s "o" parameter would be considered strong as well.  I tried dumping as much to the sys.out to make sure nothing is being optimized away.

       

      Why does my weak reference return null when - apparently to me - there *are* strong references?  Is it possible the gc would collect collect the referent if there is not enough memory - despite have a strong reference elsewhere?  Wouldn't seem like it.  Is it possible and how would you rewrite the following code to *guarantee* that the weak reference will never return null?  Maybe soft reference is what I'm looking for?  I just want it under no circumstance *ever* (translate guarantee), even when memory is tight & the gc is working hard, that I lose the referent if there is a strong reference.

       

      Thanks

       

      ______________________________________________

      public class Main {

          static Object method(final Object o) {

              final WeakReference wr = new WeakReference(o);

              final List<Integer> list = new ArrayList();

              for (int i = 0; i < 100000; ++i) {

                  list.add(i);

                  if (i % 1000 == 0) {

                      System.gc();

                  }

              }

       

       

              int total = 0;

              for (final int i : list) {

                  total += i;

              }

              System.out.println(total);

              return wr.get();

          }

       

       

          public static void main(final String[] args) throws Exception {

              final Object x = new Object();

              System.out.println(method(x));

       

              System.out.println(method(new Object()));

          }

      }

        • 1. Re: Why is my weak reference returning null?  Turing award for an answer :P
          TPD-Opitz

          Looks like the GC is somewhat smarter than you think.

          Somehow it finds out if the strong reference to the object is still needed after GC run.

          You can proove that by adding System.out.println(o); before the return statement. Than magically the second println() in main also shows a non null value...

           

          bye

          TPD

          1 person found this helpful
          • 2. Re: Why is my weak reference returning null?  Turing award for an answer :P
            baftos

            I tried myself this kind of things and I thought along the same lines. The only difference is that I blamed it on JIT optimizations instead of the GC, but this is splitting hairs.

            While looking at the Java code, we can say that o runs out of scope after method() returns, but probably the JIT considers it out of scope earlier.

            • 3. Re: Why is my weak reference returning null?  Turing award for an answer :P
              rp0428
              Why does my weak reference return null when - apparently to me - there *are* strong references?

              What 'strong' reference are you referring to?

              System.out.println(method(new Object()));

              The only 'strong' reference there is the 'new Object()' constructed BEFORE the method call.

               

              Then when that method call is made the 'main' method code no longer has a strong reference to that new object.

                   static Object method(final Object o) {

              That parameter is a local reference to the object.

              final WeakReference wr = new WeakReference(o);

              Once that statement executes there are no more strong references to the object.

               

              So the object can be finalized and collected. If it is collected then this line will print 'null'

              System.out.println(method(new Object()));

              Use a GUI like NetBeans and put a breakpoint on this line:

                   return wr.get();

              Run the debugger and when it stops at that breakpoint the second time take two more 'steps' and examine the output window and the object will now be printed and not be null.

              • 4. Re: Why is my weak reference returning null?  Turing award for an answer :P
                1059726

                I'm inclined to agree with you on this.  When looking @ the class file dump, the delaration of the stack frame for "main" only has one variable declared "x".  In the byte code, x assigned to a stack frame variable and rval - as expected - wasnt but just "dup"ed.  I'm thinking *rval's aren't considered strong* and that the jvm will mark it as strongly referenced if it is strongly referenced in a child stack frame or some other thread's stack at the time of gc.

                 

                 

                Thanks

                • 5. Re: Why is my weak reference returning null?  Turing award for an answer :P
                  rp0428
                  I'm thinking *rval's aren't considered strong* and that the jvm will mark it as strongly referenced if it is strongly referenced in a child stack frame or some other thread's stack at the time of gc.

                  And I'm thinking I already told you that in my reply above that answers your question. Did you try using the debugger as I suggested?

                  • 6. Re: Why is my weak reference returning null?  Turing award for an answer :P
                    EJP

                    > Once that statement executes there are no more strong references to the object.

                    That's not correct. The reference in the parameter 'o' still exists.