Re: A Java Brainteaser - a Static Factory method Narrative



On Sat, 2005-05-14 at 07:14 -0700, krasicki wrote:
> John C. Bollinger wrote:
> > krasicki wrote:
> >
> > > Andrew McDonagh wrote:
> -snip-
> > >>The garbage collector is responsible for objects actual
> destruction. As
> > >>a programmer you have no control over when the garbage collector
> runs.
> > >>At best you can ask the CG to run, but it is up to the CG (based on
> its
> > >>own algorithms) whether it will run.
> > >
> > >
> > > I disagree. When a Java programmer invokes a System.gc() call it
> frees
> > > memory to the JVM at the earliest algorithmically determined time.
> >
> > It depends what you mean by that. System.gc() requests that the GC
> make
> > its best effort to reclaim unreachable objects. Depending on the GC
> > implementation, that "best effort" could conceivably be no special
> > action whatsoever. This is what I believe Andrew was describing.
>
> I'm suspicious of that idea. When I read Rod Johnson's assertions
> today's JVM machinations are far from do nothing algorithms. They are
> sifting and sorting this stuff for efficiency.
>

But the point is it *looks* the same. It can be doing whatever it wants
but because the GC is completely encapsulated in the implementation it
must always maintain the various contracts involved. It must be
transparent. For most real purposes, it *is* the same - it's only when
you start getting into JNI (dont!), BCEL, Classloading and so on that
you must consider the *exact* lifecycle of objects and references.

> The larger argument is this. The static method I'm describing is
> invoked for every web-based visitor. The server is rebooted every
> night due to performance problems. I know - hard to believe but I'm
> the firefighter not the originator of any of this.
>
> I'm trying to determine if this static factory method might be
> contributing to this problem.
>

Is this a windoze box? In my experience, this kind of problem is
actually fairly rare with Java. I guess it's purely because the JVM
handles all the mallocs on the programmer's behalf, so it's a simple
thing to ensure memory is not leaked (relatively, from the JVM team's
POV).

This is not to say you *can't* leak memory, just that you *shouldn't*
unless you try (notwithstanding JVM bugs etc).

> > I disagree. There are cases where it is advantageous to set
> references
> > to null, which may allow the GC to clean up an object sooner than it
> > otherwise would do, but usually it is clearer and easier to simply
> let
> > references go out of scope. It's part of the GC's *job* to recognize
>
> > which objects it can reclaim, and nullifying references that are
> about
> > to go out of scope or become themselves unreachable anyway just isn't
>
> > worth the cost in development time, code clarity, and maintenance.
>
> Oh, let's argue this. The proverbial saying, "as above, so below"
> should not be taken so lightly. I will argue that cleaning up after
> oneself is not confusing, nor creates maintenance problems. It makes
> it explicit that no objects are being orphaned.
>

This comes back to the fundementals of Garbage Collection - an object is
eligable for collection when it is 'orphaned' (this is simplistic but
essentially true). Nulling *references* is a valid technique if you have
need to 'free' objects (e.g. in a long loop) but I am with John on the
general case, in that it's better to let a variable go out of scope.

Look at it this way - when a reference loses scope the JVM throws it
away in effect, leaving the object 'unreachable' and hence eligable for
the bin (next time the JVM goes into the kitchen). So what's the point
of writing "finished with" all over it first? The JVM will still rewrite
the message, which is after all an implementation note to itself (in a
way).

(I know it doesn't quite work when the technical aspects are considered,
so let's not consider the technical aspects for a moment - I believe you
need to step back and view the wood for a while...)

> >
> > > My question really comes back to a nagging doubt. Can an object
> > > created by a factory class from a static method ever be clean
> enough to
> > > free up? In other words, does the fact that it has referential
> roots
> > > from a static method make the byproducts of that method all look
> > > statically active (or immutable) to the GC?
> >
> > There are no "referential roots". Java does not know or care about
> the
> > origin of a reference. It cares only about whether the reference,
> and
> > thus its referent, is accessible from a live thread.
>
> But it is not Java we're refering to. Isn't the GC part of the JVM
> functionality?
>

This is a misunderstanding. In Java the term 'referential roots' has no
meaning. The JLS simply uses it to refer to a top-level reference that
is in scope. If an object has no roots in the referential set (I.e. in
scope vars of *all kinds*) then it is, by definition, unreachable.
This is how the whole thing about losing a Map full of objects works,
simply by throwing away the map ref (your root reference in this case).

The GC Implementation is part of the JVM, but Garbage Collection,
referential roots, reference counting and all that predate Java. The
root set is simply a detail of the JVM implementation and has no bearing
on this argument whatsoever.

> >
> > > Rod Johnson, in J2EE Development without EJB, talks about
> generational
> > > garbage collection techniques. Can anyone put static factory
> methods
> > > into context considering these techniques?
> >
> > Static methods are not in any way special relative to generational
> > garbage collection. Generational GC is concerned with how old an
> object
> > is, and thus _when_ it was created. Generation GC, like Java in
> > general, doesn't care a whit about _how_ it was created.
> >
> Then why would nulling an object provide a hint to the GC that an
> object is exhausted?
>

In the same way that when a reference goes out of scope, the reference
you set to null is removed from that object's reference count when you
make the assignment (or just after I think). Periodically, the JVM runs
through all it's objects (for example), and every one it finds with a
zero reference count (indicating it's not reachable) is eligable for GC.
Note this doesn't necessarily mean they *will* be collected, especially
when we factor in active threads and whatnot, but you get the idea.

I would expect that even internally there is no 'ordinary' way to know
at GC time how or where an object was allocated.

Cheers,
Ross

--
[Ross A. Bamford] [ross AT the.website.domain]
Roscopeco Open Tech ++ Open Source + Java + Apache + CMF
http://www.roscopec0.f9.co.uk/ + info@xxxxxxxxxxxxxxxxxx


.



Relevant Pages

  • Re: Java Memory question
    ... So many Java types are "native" in that sense, in particular, the ...  The natives are the ones ... Cloning occurs within a single JVM only. ... reference is never an object; ...
    (comp.lang.java.help)
  • Re: A Java Brainteaser - a Static Factory method Narrative
    ... > today's JVM machinations are far from do nothing algorithms. ... Todays JVM's may be implemented that way, but the Java specification doesn't ... unless that static method is called from a myriad of threads ... >> reference, and thus its referent, is accessible from a live thread. ...
    (comp.object)
  • Re: Garbage collection
    ... Tony is right and this *is* implementation dependent. ... But there's more to it than just the spec. ... JVM implementation is usable for a specific purpose. ... Another JVM implementation might use reference counting if it ...
    (comp.lang.java.programmer)
  • How the GC reclaim the memory of the objects with circled reference
    ... Let's simplify using public data member. ... look same in C# and Java): ... reference to each other. ... am pretty sure that Sun is handling it correctly in their current JVM. ...
    (comp.lang.java.programmer)
  • How the GC reclaim the memory of the objects with circled reference
    ... Let's simplify using public data member. ... look same in C# and Java): ... reference to each other. ... am pretty sure that Sun is handling it correctly in their current JVM. ...
    (microsoft.public.dotnet.languages.csharp)