Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / May 2006

Tip: Looking for answers? Try searching our database.

SoftReference operation synchronization detail

Thread view: 
Stanimir Stamenkov - 31 May 2006 16:17 GMT
The following may have more apparent effect when using a WeakReference.
Suppose I initialize a class member field which is a SoftReference, at
some point:

   SoftReference cache = new SoftReference(obj);

Then I have the following code accessing the referenced object, in a
method body:

   Object obj = null;
   if (cache != null) {
       obj = cache.get();
   }
   if (obj == null) {
       obj = new Object();   /* re-initialize obj */
       cache = new SoftReference(obj);
   }
   /* do with obj */

Is it guaranteed the 'cache' won't be cleared after the 'if (cache !=
null)' evaluates to true and prior executing the first statement in the
'if' block?

Is it guaranteed 'Reference.get()' will return a non-null result if the
corresponding SoftReference or WeakReference is not cleared yet?, so I
could go without the explicit 'obj = null' initialization in the above
example:

   Object obj;
   if (cache != null) {
       obj = cache.get();
   } else {
       obj = new Object();   /* re-initialize obj */
       cache = new SoftReference(obj);
   }
   /* do with obj */

Signature

Stanimir

Oliver Wong - 31 May 2006 16:31 GMT
> The following may have more apparent effect when using a WeakReference.
> Suppose I initialize a class member field which is a SoftReference, at
[quoted text clipped - 32 lines]
>    }
>    /* do with obj */

   I don't understand your exact question, but the information I think you
want is that second code is unsafe. cache.get() might return null. The first
code example is better. Note that the reference called "cache" won't
magically turn into null behind your back. It's only the referent within the
SoftReference which may become null (which is why get() sometimes returns
null). So depending on the design of the rest of your code, the check for
cache != null might be unnescessary.

   - Oliver
Robert Klemme - 31 May 2006 16:48 GMT
>> The following may have more apparent effect when using a WeakReference.
>> Suppose I initialize a class member field which is a SoftReference, at
[quoted text clipped - 40 lines]
> sometimes returns null). So depending on the design of the rest of your
> code, the check for cache != null might be unnescessary.

Adding to that, here's what I'd do assuming that "cache" is an instance
variable: make sure cache is always initialized with a SoftReference.
If you do not have a referent initially just use new
SoftReference(null).  Then you can simplify your code to

Object o = cache.get();

if ( o == null ) {
  o = new Object();
  cache = new SoftReference(o);
}

// work with o

The only downside of this is one additional object creation (the initial
SoftReference) which usually only makes a difference if you have a lot
of them.

Kind regards

    robert
Thomas Hawtin - 31 May 2006 19:52 GMT
> Adding to that, here's what I'd do assuming that "cache" is an instance
> variable: make sure cache is always initialized with a SoftReference. If
[quoted text clipped - 6 lines]
> SoftReference) which usually only makes a difference if you have a lot
> of them.

And if you're working in the JRE, itself trying to use the technique on
the thread class doesn't always work too well as the Reference static
initialiser attempts to starts a new thread...

Tom Hawtin
Signature

Unemployed English Java programmer
http://jroller.com/page/tackline/

stamenkov@gmail.com - 31 May 2006 18:51 GMT
/Oliver Wong/:

> Note that the reference called "cache" won't
> magically turn into null behind your back. It's only the referent within the
> SoftReference which may become null (which is why get() sometimes returns
> null). So depending on the design of the rest of your code, the check for
> cache != null might be unnescessary.

I haven't used the Reference classes up to now and seems I haven't
quite understood the description
<http://java.sun.com/j2se/1.4.2/docs/api/java/lang/ref/SoftReference.html>:

> Suppose that the garbage collector determines at a certain point in
> time that an object is softly reachable. At that time it may choose
> to clear atomically all soft references to that object...

The "choose to clear all soft references" part now I understand as
clear the references to the objects those Reference objects hold,
right?

But my main concern was because of some test of mine (not clear enough
thought) while playing with those Reference classes - I've got 'null'
values for the Reference variables themselves, after I have initialized
them. And reading further into the description:

> ... At the same time or at some later time it will enqueue those
> newly-cleared soft references...

I don't understand how are the references processed from those queues,
given the they have already been cleared, but I've speculated that
process might have cleared my Reference variables, somehow. It is quite
possible I haven't overseen something, too.

That sounds most logical, but again: a Reference variable is never
cleared automatically?

Signature

Stanimir

Oliver Wong - 31 May 2006 19:16 GMT
> /Oliver Wong/:
>
[quoted text clipped - 32 lines]
> That sounds most logical, but again: a Reference variable is never
> cleared automatically?

   First of all, we should clear up some terminology and basic concepts.
Java has variables which have values. These values are sometimes primitives:
e.g. when you have a variable of type int, then the value of the variable is
the value of that int itself, such as the value 3. Other times, the
variables act as references to objects. They "point" to the address in
memory where an object is located. So for example, with this code snippet:

<code>
Foo a;
Foo b;
a = new Foo();
b = a;
</code>

   You've got 2 variables, but only 1 object. Both variables point, or
refer to, the same object. The variables have names. There's a variable call
"a", and a variable called "b". Objects don't have names.

   Objects have classes. SoftReference is a class. So you can have an
object of type SoftReference. Consider now the following code:

<code>
SoftReference cache = new SoftReference(new Foo());
</code>

   There are 2 objects and 1 variable. There's an instance of Foo, an
instance of SoftReference, and a variable called "cache".

   Cache will never "magically" become null. If you want cache to be null,
you (or some other code) has to explicitly set it to null. So this following
code snippet will always print "Hello world!":

<code>
SoftReference cache = new SoftReference(new Foo());
if (cache == null) {
 System.out.println("This should never happen.");
} else {
 System.out.println("Hello world!");
}
</code>

However, this code may sometimes print "Hello world!", sometimes print
"Goodbye world!":

<code>
SoftReference cache = new SoftReference(new Foo());
if (cache.get() == null) {
 System.out.println("Goodbye world!");
} else {
 System.out.println("Hello world!");
}
</code>

See
http://java.sun.com/j2se/1.5.0/docs/api/java/lang/ref/package-summary.html#reach
ability


The SoftReference object in the code above is strongly reachable. Why?
Because you can directly reach it using the variable called "cache". So the
SoftReference object itself will not get garbage collected. However, the
Fooobject is softly reachable. That is, it is not strongly reachable (since
you don't have a variable which points to it), but you DO have a
SoftReference which holds it.

(This next part starts talking about underlying implementation. It makes a
bunch of simplifying assumptions, like avoiding the whole concept of "weakly
reachable" and "phantom reachable" and might not reflect what the JVM is
"really" doing under the covers, but hopefully it'll still help you
understand the external observable behaviour.)

So the garbage collector may decide it wants to collect that Foo object. The
first step in doing so is that it will tell the SoftReference to release it.
Once that happens, whenever you call the .get() method on the SoftReference
object, that method will return null. However, the Foo object has not yet
been garbage collected. It's just floating around in memory somewhere, with
no way to access it.

Now, the garbage collector can garbage collect the Foo object, without
worrying about deleting an object while it's still being used. It doesn't
have to worry, because the Foo object is unreachable. There's no
strong-references to it, and there's no soft-references to it either.

   - Oliver
Stanimir Stamenkov - 31 May 2006 20:20 GMT
/Oliver Wong/:

>> That sounds most logical, but again: a Reference variable is never
>> cleared automatically?
>
>     First of all, we should clear up some terminology and basic concepts.
[...]

Thank you and thank to Robert and Thomas for your answers. I think I
understand the basics. In the above sentence of mine "Reference"
referred to the |Reference| class and "variable" to a reference type of
variable as defined in the Java language specification.

As I've written my confusion came from some unclear tests of mine I've
made previously. I understand the intended usage of SoftReference and
WeakReference but because I'm just starting using them the unclear
result (the unclear way I've got it) appeared pretty much like "magic"
to me so I've made up some "magic" speculations in my mind and that's
why I've finally asked here for clarification.

Signature

Stanimir

Thomas Hawtin - 31 May 2006 19:54 GMT
>> ... At the same time or at some later time it will enqueue those
>> newly-cleared soft references...
[quoted text clipped - 3 lines]
> process might have cleared my Reference variables, somehow. It is quite
> possible I haven't overseen something, too.

When using ReferenceQueues, you typically subclass the Reference
implementation and add fields to that so you know what disappeared.
Alternatively you can do it on object identity of the Reference with a
map of some description.

Tom Hawtin
Signature

Unemployed English Java programmer
http://jroller.com/page/tackline/



Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.