Java Forum / General / May 2005
A Java Brainteaser - a Static Factory method Narrative
krasicki - 13 May 2005 02:28 GMT I had never run into this before but have recently encountered code that is something like:
// This code runs - I'm generalizing so forgive unintentional oversights
// from a servlet MyWidget mw = FactoryClass.staticMethod(); :
and in FactoryClass we find:
public static MyWidget staticMethod() { // yada yada return new MyWidgetObject(); }
My questions are many but first and foremost is, *how is the memory managed?* Is each new object a new static object with immutable memory assigned it or is the static memory recycled with each assignment to mw?
Disclaimer: YES,YES,YES - I know, I know... but take it for what it's worth.
Wibble - 13 May 2005 02:44 GMT The method to create a widget is static. Not the widget allocated. Its a plain old java object.
> I had never run into this before but have recently encountered code > that is something like: [quoted text clipped - 20 lines] > Disclaimer: YES,YES,YES - I know, I know... but take it for what it's > worth. krasicki - 13 May 2005 03:11 GMT Are there garbage collection issues with these objects?
Wibble - 13 May 2005 04:17 GMT > Are there garbage collection issues with these objects? No, its irrelevant that they're allocated from a static method. It just allows the Factory class a little more control of object creation than the 'new' method by itself.
In your example, the static just calls new. Its a POJO.
krasicki - 13 May 2005 05:08 GMT Alright, I'll buy that. Let me reiterate what you're saying, just to be clear.
If my example was (instead of a servlet lifecycle);
// from a short term object instance MyWidget mw = FactoryClass.staticMethod();
then mw would be garbage collected just like any other object that got instantiated for it. Preferably, object mw will have its own housekeeping method that cleans up its particulars so that the same object that instantiated mw could eliminate it like so (more or less):
mw.cleanUp(); mw = null;
Furthermore, a static method used as a Factory, generally speaking, should add value (performance, convenience, or otherwise) to the dispensing of the new object.
Now, at face value, it would seem that all factory objects in non-distributed application container contexts should be implemented this way assuming the class is efficient.
As a rule of thumb, would I be correct in suggesting that factory methods should be static when they serve the broadest utilitarian purposes and classes should be instantiated for their method access for more specialized processing purposes?
Finally, when would using this technique be good or bad practice. After all, this technique seems to violate strict object-oriented implementation practice.
Andrew McDonagh - 13 May 2005 08:03 GMT > Alright, I'll buy that. Let me reiterate what you're saying, just to > be clear. [quoted text clipped - 28 lines] > After all, this technique seems to violate strict object-oriented > implementation practice. All java objects are the same in terms of memory management (creation and removal). It is irrelevant that a static method just happened to be used to create the object.
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.
Java objects do not have C++ style destructor. They can override Object.finalize(), this method MAY be called at sometime if the object is being CGed, but there is no guarantee. So its better to directly call your own 'cleanup' method to close File, sockets type resources.
As for static factory methods, they are fine if used sparingly. Its usually more helpful to have a factory method on an instance of the factory - then you can override if necessary in a derived factory class.
krasicki - 13 May 2005 21:34 GMT -snip-
> All java objects are the same in terms of memory management (creation
> and removal). It is irrelevant that a static method just happened to be > used to create the object. I want to explore that subject. Take all my arguments as good natured curiosity.
> 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. In fact, I read an IBM or BEA article recently that advised programmers not to use it because the application server's own garbage collection management would get screwed up and you would likely hurt more than help performance.
But let's get even more subtle. Hagar, Bulka, and other java stylists recommend explicit cleanup in deeply nested objects. In other words, deeply nested cleanup routines that return exhausted object instances back to a state of null. This, we are told, hints to the GC that it's okay to free the associated memory.
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?
Rod Johnson, in J2EE Development without EJB, talks about generational garbage collection techniques. Can anyone put static factory methods into context considering these techniques?
-snip-
> As for static factory methods, they are fine if used sparingly. Don't you really mean appropriately. Will using them a lot be worse or better than using them a little. What does their proliferation have to do with it?
> Its > usually more helpful to have a factory method on an instance of the > factory - then you can override if necessary in a derived factory class. Understood.
Daniel Sjöblom - 13 May 2005 22:35 GMT <snip stuff>
> 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? It seems that somewhere along the road you have gotten thoroughly confused about how garbage collection works. As such, it is hard to answer your question, since you are likely to misinterpret the answer. Please read this for some basic information about garbage collection: http://java.sun.com/developer/technicalArticles/ALT/RefObj/
To quote the most relevant parts:
(QUOTE) The garbage collector's job is to identify objects that are no longer in use and reclaim the memory. What does it mean for an object to be in use?
Note: An object is in use if it can be accessed or reached by the program in its current state.
An executing Java program consists of a set of threads, each of which is actively executing a set of methods (one having called the next). Each of these methods can have arguments or local variables that are references to objects. These references are said to belong to a root set of references that are immediately accessible to the program. Other references in the root set include static reference variables defined in loaded classes, and references registered through the Java Native Interface (JNI) API.
All objects referenced by this root set of references are said to be reachable by the program in its current state and must not be collected. Also, those objects might contain references to still other objects, which are also reachable, and so on.
All other objects on the heap are considered unreachable, and all unreachable objects are eligible for garbage collection. (UNQUOTE)
Note especially the part about /actively executing/ methods. Once a method returns, any local references in that method are no longer part of the root set.
 Signature Daniel Sjöblom Remove _NOSPAM to reply by mail
Ross Bamford - 14 May 2005 04:11 GMT On Sat, 2005-05-14 at 00:35 +0300, Daniel Sj=B6blom wrote:
> <snip stuff> > > My question really comes back to a nagging doubt. Can an object [quoted text clipped - 39 lines] > method returns, any local references in that method are no longer part > of the root set. I think the source of OPs confusion may be the sentence (fragment) "Other references in the root set include static reference variables defined in loaded classes, ...", taken as meaning all reference variables rather than reference member variables only.
As a more general thing, this confusion is probably an example of the adage that "a little knowledge is a dangerous thing" (and I mean no offence by this at all). I am merely suggesting the OP might want to revisit some of the more fundemental Java concepts before hitting the metal with BEA references or the more technical J2EE journals.
Ross
 Signature [Ross A. Bamford] [ross AT the.website.domain] Roscopeco Open Tech ++ Open Source + Java + Apache + CMF http://www.roscopec0.f9.co.uk/ + info@the.website.domain
paul campbell - 13 May 2005 22:41 GMT > 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? No.
Returning a value from a method doesnt create a reference (static or not) so the GC isnt interested in it.
Paul C.
> Rod Johnson, in J2EE Development without EJB, talks about generational > garbage collection techniques. Can anyone put static factory methods [quoted text clipped - 7 lines] > better than using them a little. What does their proliferation have to > do with it? Use one when it solves a specific problem for you.
Using them indiscriminately makes code harder to read.
Paul C.
krasicki - 14 May 2005 15:01 GMT > > In other words, does the fact that it has referential roots > > from a static method make the byproducts of that method all look [quoted text clipped - 4 lines] > Returning a value from a method doesnt create a reference (static > or not) so the GC isnt interested in it. Paul,
Explain this a bit.
A class that contains a static method does not have to be instantiated.
That method occupies a certain amont of memory in the JVM allocation. Do all of the POGOs created from that method extend that static footprint or do they simply get created initially as short-term memory footprints?
Once I say x = FactoryClass.staticMethodObject();
I have an object that may involve many objects within objects.
When I say, x = null;
I'm hinting to the GC that I'm done with it. But does the GC look at it and say, hey, it's part of static memory, leave it there or is the implicit assumption to return it to free memory.
> > Rod Johnson, in J2EE Development without EJB, talks about generational > > garbage collection techniques. Can anyone put static factory methods [quoted text clipped - 11 lines] > > Using them indiscriminately makes code harder to read. Once again, I must (in good humor) protest. Couldn't somebody say, "Hey, if you can read it once, can't you read it twice? three times? and so on? What's so hard to read?
Isn't this more a case of familiarity breeding contempt?
Joona I Palaste - 14 May 2005 16:26 GMT krasicki <Krasicki@gmail.com> scribbled the following on comp.lang.java.programmer:
>> > In other words, does the fact that it has referential roots >> > from a static method make the byproducts of that method all look [quoted text clipped - 4 lines] >> Returning a value from a method doesnt create a reference (static >> or not) so the GC isnt interested in it.
> Paul,
> Explain this a bit.
> A class that contains a static method does not have to be instantiated.
> That method occupies a certain amont of memory in the JVM allocation. > Do all of the POGOs created from that method extend that static > footprint or do they simply get created initially as short-term memory > footprints?
> Once I say x = FactoryClass.staticMethodObject();
> I have an object that may involve many objects within objects.
> When I say, x = null;
> I'm hinting to the GC that I'm done with it. But does the GC look at > it and say, hey, it's part of static memory, leave it there or is the > implicit assumption to return it to free memory. As far as the GC and memory management are concerned, it makes *NO DIFFERENCE WHATSOEVER* whether the object was constructed in a static method or in an instance method. Not even the slightest bit. The object does not retain any sort of information about which method created it, unless you explicitly tell it, by calling a method or setting a member variable. This is true for both objects created in static methods and ones created in instance methods.
 Signature /-- Joona Palaste (palaste@cc.helsinki.fi) ------------- Finland --------\ \-------------------------------------------------------- rules! --------/ "You will be given the plague." - Montgomery Burns
paul campbell - 25 May 2005 13:50 GMT >> > In other words, does the fact that it has referential roots >> > from a static method make the byproducts of that method all look [quoted text clipped - 15 lines] > footprint or do they simply get created initially as short-term memory > footprints? Your extrapolating from an acute lack of understanding of the fundamentals of program process memory management - like somone walking into a chemical research lab and trying second guess what reactions are going to take place based on the colour of the chemicals being mixed.
You need to go back to basics and study memory managment in modern OS processes - nevermind trying understand GC.
Paul C.
krasicki - 26 May 2005 02:06 GMT > >> > In other words, does the fact that it has referential roots > >> > from a static method make the byproducts of that method all look [quoted text clipped - 20 lines] > research lab and trying second guess what reactions are going to take > place based on the colour of the chemicals being mixed. You seem to be addressing me. Everything I've read says that the JVM manages its own memory management. Program process management is far too general for this discussion because we are really talking about Java.
But the tone of this post is not about solving problems or enlightening anyone, it's just a slam. Feel better?
> You need to go back to basics and study memory managment in modern OS > processes - nevermind trying understand GC. Spoken like a gentleman and a scholar.
paul campbell - 30 May 2005 18:55 GMT >> >> > In other words, does the fact that it has referential roots >> >> > from a static method make the byproducts of that method all look [quoted text clipped - 26 lines] > You seem to be addressing me. Everything I've read says that the JVM > manages its own memory management. The VM is a virtual processor executing vitual machine code in a virtual process which follows the same basic principals of memory managment as a real process i.e. it has seperate "areas" for executable code, stack, heap, statics etc. Furthermore java objects and classes and thier constituent parts are divied up into these areas in much the same way as real code (say c++) is handled in a real process.
If you undestood this then you would understand why you are so far off base with your reasoning about VM memory managment.
I say again that you are trying to reason from an unsound foundation of knowledge - you are trying to understand CG behaviour without an understanding of more fundamental concepts about how the various aspects of objects and classes map onto diferent types of memory in a running process (real or virtual).
>> You need to go back to basics and study memory managment in modern OS >> processes - nevermind trying understand GC. I stand by that statement, you arnt going to get any further with your understanding util you take that advice.
Paul C.
John C. Bollinger - 14 May 2005 00:02 GMT >>All java objects are the same in terms of memory management (creation >>and removal). It is irrelevant that a static method just happened to be [quoted text clipped - 10 lines] > 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.
> In > fact, I read an IBM or BEA article recently that advised programmers > not to use it because the application server's own garbage collection > management would get screwed up and you would likely hurt more than > help performance. More the *VM's* GC. I am not aware of any application server that provides any particular "garbage collection management", nor do I really see how any could be provided outside tweaking or configuring the VM, whether the app server wanted to or not. The article may have been quite correct, however, in that a program frequently invoking System.gc() might cause the garbage collector to expend considerably more effort than it otherwise would do, for no particular gain.
> But let's get even more subtle. Hagar, Bulka, and other java stylists > recommend explicit cleanup in deeply nested objects. In other words, > deeply nested cleanup routines that return exhausted object instances > back to a state of null. This, we are told, hints to the GC that it's > okay to free the associated memory. 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.
> 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.
> 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.
 Signature John Bollinger jobollin@indiana.edu
krasicki - 14 May 2005 15:14 GMT -snip-
> >>The garbage collector is responsible for objects actual destruction. As > >>a programmer you have no control over when the garbage collector runs. [quoted text clipped - 8 lines] > 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.
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.
> > In > > fact, I read an IBM or BEA article recently that advised programmers [quoted text clipped - 5 lines] > provides any particular "garbage collection management", nor do I really > see how any could be provided outside tweaking or configuring the VM,
> whether the app server wanted to or not. Sorry. I've been overly busy lately so I haven't had time to do more than type stream of consciousness thoughts.
You are correct about the JVM and GC. But I think that container managed issues contribute to this best practice suggestion that System.gc() not be used.
> The article may have been > quite correct, however, in that a program frequently invoking > System.gc() might cause the garbage collector to expend considerably > more effort than it otherwise would do, for no particular gain. Yes.
> > But let's get even more subtle. Hagar, Bulka, and other java stylists > > recommend explicit cleanup in deeply nested objects. In other words, [quoted text clipped - 6 lines] > 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.
> > 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 [quoted text clipped - 5 lines] > 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?
> > Rod Johnson, in J2EE Development without EJB, talks about generational > > garbage collection techniques. Can anyone put static factory methods [quoted text clipped - 4 lines] > 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?
Ross Bamford - 14 May 2005 18:25 GMT > -snip- > > >>The garbage collector is responsible for objects actual [quoted text clipped - 18 lines] > 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 [quoted text clipped - 3 lines] > 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 [quoted text clipped - 13 lines] > 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 [quoted text clipped - 12 lines] > 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 [quoted text clipped - 10 lines] > 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
 Signature [Ross A. Bamford] [ross AT the.website.domain] Roscopeco Open Tech ++ Open Source + Java + Apache + CMF http://www.roscopec0.f9.co.uk/ + info@the.website.domain
Lee Fesperman - 14 May 2005 20:27 GMT > > > > My question really comes back to a nagging doubt. Can an object > > > > created by a factory class from a static method ever be clean [quoted text clipped - 15 lines] > 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). Ok, in general.
> 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. No modern JVM/GC uses reference counting.
> > > > Rod Johnson, in J2EE Development without EJB, talks about > > > > generational garbage collection techniques. Can anyone put [quoted text clipped - 15 lines] > Note this doesn't necessarily mean they *will* be collected, especially > when we factor in active threads and whatnot, but you get the idea. Again, reference counting is not the way GC works, today; it works purely by reachability analysis. Reference counting can produce 'orphans'. I think you should educate yourself better because you are adding to the confusion in this thread.
 Signature Lee Fesperman, FFE Software, Inc. (http://www.firstsql.com) ============================================================== * The Ultimate DBMS is here! * FirstSQL/J Object/Relational DBMS (http://www.firstsql.com)
Ross Bamford - 14 May 2005 21:03 GMT > No modern JVM/GC uses reference counting.
> Again, reference counting is not the way GC works, today; it works purely by > reachability analysis. Reference counting can produce 'orphans'. I think you should > educate yourself better because you are adding to the confusion in this thread. I'd argue that a lot more confusion comes from messages highlighting out-of-date facts that are actually irrelevant to the discussion. Okay, so reference counting isn't used any more - the point is, I don't need to know or care from a development point of view, because it 'just works' regardless of where or how I instantiate new objects.
In any case the intent is the same - an object unreachable object has no references. Whether you counted them, tracked them, or registered details in a database every time one was used (;)), the point is that you know, in the, end, that there are none.
However, I do apologise for my error - I must admit I am only really an enthusiast when it comes to the JVMs deep internals.
Ross
 Signature [Ross A. Bamford] [ross AT the.website.domain] Roscopeco Open Tech ++ Open Source + Java + Apache + CMF http://www.roscopec0.f9.co.uk/ + info@the.website.domain
Lee Fesperman - 14 May 2005 23:06 GMT > > No modern JVM/GC uses reference counting. > [quoted text clipped - 7 lines] > to know or care from a development point of view, because it 'just > works' regardless of where or how I instantiate new objects. Ok, that's true enough in terms of most of the confusion on this thread and in terms of where or how you instantiate new objects, but ...
> In any case the intent is the same - an object unreachable object has no > references. Whether you counted them, tracked them, or registered > details in a database every time one was used (;)), the point is that > you know, in the, end, that there are none. The problem with reference counting (and, probably, the other methods you mentioned) is circular references. In a circular reference, 2 or more objects reference each other, so even though they are not reachable from live code, they don't have a reference count of zero. These could be called orphans, which the OP did mention, thus I didn't want you to cause him concern over that issue.
 Signature Lee Fesperman, FFE Software, Inc. (http://www.firstsql.com) ============================================================== * The Ultimate DBMS is here! * FirstSQL/J Object/Relational DBMS (http://www.firstsql.com)
Ross Bamford - 15 May 2005 02:19 GMT > > > No modern JVM/GC uses reference counting. > > [quoted text clipped - 21 lines] > zero. These could be called orphans, which the OP did mention, thus I didn't want you to > cause him concern over that issue. Which, then, is where the fact that even if an object has one or more actual references, if it cannot be referenced from the 'root set' (see earlier) that fact is discounted (since it isn't reachable). Of course, it makes sense. I was even contradicting myself ;)
I wonder if you could recommend a good link for a (quick) knowledge update?
Ross
 Signature [Ross A. Bamford] [ross AT the.website.domain] Roscopeco Open Tech ++ Open Source + Java + Apache + CMF http://www.roscopec0.f9.co.uk/ + info@the.website.domain
Daniel Sjöblom - 14 May 2005 21:27 GMT > 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 [quoted text clipped - 3 lines] > 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'm not aware of any JVMs that use reference counting for GC. The problem with reference counting is that objects that circularily point to each other will be considered live, even though there is no way to reach them from 'the outside' so to speak. I'll explain a bit further about the approach normally taken in JVMs.
The basic idea in most JVMs is to keep track of which objects at time A could possibly be accessed by the program, with the help of something called reachability analysis. If we consider a simplified JVM with no static variables and no JNI, and only one thread running, the program at a point A looks something like this on the stack:
-------------
| main method -------------
| method a -------------
| method b -------------
| method c <- Currently executing method c. -------------
Where the method call chain is main -> a -> b -> c. Suppose we suspend the program at this point, and wish to compute the set of all currently reachable objects. How do we do this? If we do some preparation, it is not too hard. Before we run any method, we calculate a garbage collection map for the method. This will simply be a data structure that contains information about which local variables in the method can contain references to objects. For instance, it might look like this (*):
public class GCMap { int[] framePointerOffsets; }
where framePointerOffsets contains the adresses (relative to the framepointer) of local variables that contain references.
So, now all we need to do this is walk the stack backwards and with the help of the garbage collection maps add all the references currently contained in the local variables of each method to a set, which we will call the root set. The code could like this:
Set rootSet = empty
for stackframe in stack for offset in framePointerOffsets in GCMap of method at stackframe rootSet = rootSet U (value at (framePointer + offset))
So now we have our root set. The last thing we need to do is follow all of the references in the root set to find other live references and from those references go to yet others and so on. This can be done with a standard graph search. If some object is not reachable from the root set of references, it cannot possibly be accessed by the program anymore, and as such is garbage which can be collected.
This is a simplified explanation of a very simple reachability analysis, in reality things are more complicated (and there are various alternative procedures for achieving the same goals). This example should however also explain why references may need to be 'nulled' at times. In the gathering of references to the root set, we are only considering the state of the program at point A, and ignoring anything that may happen in the future. For instance, we may have a reference in a local variable at point A which is never read (never used) again in the future. But our analyzer does not know this! Hence we (as programmers) may need to manually 'null' references in certain methods, when we know that a reference points to an object we will not use anymore.
* we assume all local variables are on the stack
-------------
 Signature Daniel Sjöblom Remove _NOSPAM to reply by mail
Laurent Bossavit - 15 May 2005 09:23 GMT Krasicki,
> 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'm trying to determine > if this static factory method might be contributing to this problem. It's not; or rather, the sole fact that it's static is not a sufficient or a necessary condition for this kind of problem to arise. It's irrelevant. A thread's stack is the root of all object references, together with static instance *variables*. The keyword static means something different altogether for methods - unfortunate overloading of the name. At any rate, a stack frame for a static method is not treated differently from a stack frame of a regular method.
Get yourself a copy of OptimizeIt or similar. It's possible to debug such problems "statically" - by which I mean through the sole means of reading the source code; I've done it a few times. A profiler is a quicker way, and it will locate the problem even if it's not due to your own code but rather to some third-party code.
Interaction between the language and the GC should be covered by the Java Language Specification - have you read that ? Section 12.6 covers object finalization.
See also: http://java.sun.com/docs/books/performance/1st_edition/html/JPAppGC.fm.h tml
Laurent
krasicki - 16 May 2005 02:59 GMT > Krasicki, > [quoted text clipped - 10 lines] > the name. At any rate, a stack frame for a static method is not treated > differently from a stack frame of a regular method. Bingo - best answer. Let's repeat it, *The keyword static means
> something different altogether for methods - unfortunate overloading of > the name.* This is what confused me most and something I have never seen said in a technical discussion.
> Get yourself a copy of OptimizeIt or similar. It's possible to debug > such problems "statically" - by which I mean through the sole means of > reading the source code; I've done it a few times. A profiler is a > quicker way, and it will locate the problem even if it's not due to your > own code but rather to some third-party code. Yes, good advice for shops that take advice.
> Interaction between the language and the GC should be covered by the > Java Language Specification - have you read that ? Section 12.6 covers > object finalization. > > See also: http://java.sun.com/docs/books/performance/1st_edition/html/JPAppGC.fm.h
> tml Thanks. Yeah I read a lot but it's overwhwelming and everything gets dated very quickly. I had not run across this before and being someone who likes OO programming I don't look for workarounds - hence a blindspot with this subject.
Laurent Bossavit - 16 May 2005 07:08 GMT Krasicki,
> Yes, good advice for shops that take advice. There you have it - the Consultant's Ultimate Frustration. Pretty much the same as the architect's, right ?
Laurent
Rich MacDonald - 17 May 2005 05:10 GMT "krasicki" <Krasicki@gmail.com> wrote in news:1116208763.211291.313660 @o13g2000cwo.googlegroups.com:
> Bingo - best answer. Let's repeat it, *The keyword static means >> something different altogether for methods - unfortunate overloading > of >> the name.* This is what confused me most and something I have never > seen said in a technical discussion. Never could have guessed that was what was hanging you up. Prior language hangover? Yeah, I've just been reading this thinking "this is obvious, he can't be serious, but he needs a shakeout, so go with the flow."
With my Smalltalk background, a static method is just another place where things can happen ---> the *same* happenings that all methods follow. Is an object created? Does something point to it when the method is complete? Then it follows the same rules as always. Nothing to it. Don't overcomplicate the thought process.
> http://java.sun.com/docs/books/performance/1st_edition/html/JPAppGC.fm.h >> tml [quoted text clipped - 3 lines] > who likes OO programming I don't look for workarounds - hence a > blindspot with this subject. Although an aside at this point, the object reference nullifying is a workaround, and hopefully an old wive's tale that's no longer relevant.
krasicki - 18 May 2005 03:21 GMT > "krasicki" <Krasicki@gmail.com> wrote in news:1116208763.211291.313660 > @o13g2000cwo.googlegroups.com: [quoted text clipped - 8 lines] > hangover? Yeah, I've just been reading this thinking "this is obvious, he > can't be serious, but he needs a shakeout, so go with the flow." No, it was not 'hanging me up' but you're missing a back story context. The code I was evaluating came with a requirements document that was really a narrative functional specification. And it said, more or less, "I'm using this technique to save memory."! That completely turned me around and ignited a search for such effect and when none was found, then this thread.
I'm smart enough to know I may not know and dumb enough to ask. My hunch that this had nothing to do with saving memory I think is correct but I was unsure of the scope and effect of the static keyword on the factory method byproducts.
> With my Smalltalk background, a static method is just another place where > things can happen ---> the *same* happenings that all methods follow. Is an > object created? Does something point to it when the method is complete? > Then it follows the same rules as always. Nothing to it. Don't > overcomplicate the thought process. http://java.sun.com/docs/books/performance/1st_edition/html/JPAppGC.fm.html
This link is a bit crusty so I looked further. Check this out;
http://today.java.net/pub/a/today/2003/12/30/staticsSQ1.html
> Although an aside at this point, the object reference nullifying is a
> workaround, and hopefully an old wive's tale that's no longer relevant. Indeed. Take a look at what some gamers think of my old wives technique;
http://www.javaspecialists.co.za/archive/Issue060.html
Virgil Green - 19 May 2005 22:18 GMT > Krasicki, > [quoted text clipped - 11 lines] > method is not treated differently from a stack frame of a regular > method. I'm curious to know how you think the keyword static is different for variables and methods. I've always taken it to mean the same thing for both... members of a class rather than an instance of a class (or, an object, if you will).
Anyway, I've read most of this thread and it seems that the entire point that was missed by the OP was that objects are always created in the heap and only references are found on the stack (flameproof suit on in case I've oversimplified). When a static method creates an object it may retain a reference to it only as long as any reference variables stay within scope on the stack. There isn't any memory associated with the static method that "grows" as new objects are created. The static method's memory could be said to be the stack frame(s) created when the method is invoked... there are no objects in that memory and the references in that memory go out of scope when the stack frame is "popped" off the stack.
Anyway, oversimplification, I'm sure -- but I hope it helped rather than hurt the discussion.
 Signature Virgil
krasicki - 26 May 2005 02:19 GMT Virgil,
I missed your post earlier. Thanks for the reply. At the time I was evaluating some very suspicious code and my last excursion into such issues was a number of years ago. The author in question almost exclusively uses static methods and claimed to save memory. I began looking for proof this was true (I am open to the idea that things change and maybe there's something new going on here).
The current environment I'm in is very basic but I was tryinng to remember Jprobe documentation and some other dated techniques about memory management. A few years ago, nulling deep objects was recommended and that idea still exists if you reference some f the material I link to elsewhere. Today the practice is senseless but I didn't know that for sure going into this discussion.
There remains an antiseptic idea that objects cannot be 'orphaned' in memory but I don't know if that's absolutely true. Again, that's why I thought exploring these ideas in one place made sense.
Your contribution added value. Thanks.
Laurent Bossavit - 26 May 2005 07:05 GMT Krasicki,
> There remains an antiseptic idea that objects cannot be 'orphaned' in > memory but I don't know if that's absolutely true. One more enlightening read: http://www.szegedi.org/articles/memleak.html
Laurent
Andrew McDonagh - 14 May 2005 19:59 GMT > -snip- > [quoted text clipped - 8 lines] > I want to explore that subject. Take all my arguments as good natured > curiosity. take mine with the same good natured, willing advice.
Hopefully by now, all of the other replies within this thread has shown you that the GC works to its own rules. If we haven't then thats our fault - we need to find a way to describe it to you.
>>The garbage collector is responsible for objects actual destruction. > [quoted text clipped - 12 lines] > I disagree. When a Java programmer invokes a System.gc() call it frees > memory to the JVM at the earliest algorithmically determined time. This is what I was talking about - at the 'earliest'. However, you need to remember that 'earliest' might be only be at application shutdown time.
In
> fact, I read an IBM or BEA article recently that advised programmers > not to use it because the application server's own garbage collection > management would get screwed up and you would likely hurt more than > help performance. > > But let's get even more subtle. Is that wise ;-)
> Hagar, Bulka, and other java stylists > recommend explicit cleanup in deeply nested objects. In other words, > deeply nested cleanup routines that return exhausted object instances > back to a state of null. This, we are told, hints to the GC that it's > okay to free the associated memory. What they mean by this, is that its easy in Java (and any other auto memory manged language) to hold onto memory for unnecessarily long times. This really is the only practical reason for nulling a reference
consider (very simple example)....
public void someMethodThatRunsForaLongTime() {
List aList = new ArrayList();
for (int i=0; i!= 100000;i++) { aList.add("string = " + i); }
// so now we have a huge arrayList with 100,000 string objects // referenced by it - so thats 100,001 objects we have created
int listSize = aList.size();
for (int i=0;i!= 100000;i++) { System.out.println(i); }
} // only here at the end of the method, will the local reference 'aList' go out of scope and therefore the object that it points to, is no 'orphaned' - which means the next time the GC runs, its can release the memory of the arrayList and its contents.
However, if we put the line
aList = null;
just after we save the size of the aList in the 'listSize' int, then we have made the object that the 'aList' reference points to, orphaned much early that having to wait for the method to finish.
This is a very contrived example to show the concept of holding onto objects for longer than is actually needed, but hopefully it serves its purpose.
> 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? At best as a developer we can System.gc, but the GC does not guarantee to do anything right then as a result of the call.
In general sun's JVMs GC does most of the time, tend to run when System.gc is called, but as developers we can't rely upon it happening or continuing to work that way with either different runs of the application or indeed with future JVM releases.
Therefore, we should not design our java apps with System.gc calls to release memory, as they will not behavior the same from one run to another.
> Rod Johnson, in J2EE Development without EJB, talks about generational > garbage collection techniques. Can anyone put static factory methods > into context considering these techniques? Again, static methods make no difference to the life times of objects.
> -snip- > >>As for static factory methods, they are fine if used sparingly. > > Don't you really mean appropriately. Actually I mean both of those.
>Will using them a lot be worse or > better than using them a little. What does their proliferation have to > do with it? The main problem with lots of static methods (although I'd call them 'functions'), is that they make the implementation of your application, procedural rather than OO.
By this I meam, we lose all of the benefits of objects, as these functions do not live on an object instance - they live on the class.
They can be useful for utility functions like 'System.out.println(".."); '. and are very useful for factory methods like yours or on a Singleton.
Other than that, try to prefer an instance method of an object.
>>Its >>usually more helpful to have a factory method on an instance of the [quoted text clipped - 3 lines] > > Understood. Ross Bamford - 14 May 2005 20:51 GMT > Therefore, we should not design our java apps with System.gc calls to > release memory, as they will not behavior the same from one run to another. In fact, I would have preferred a strategy where no GC 'suggestion' is offered at all in the standard Runtime, and integrators must insert custom implementation (perhaps of a specific GCManager so as not to expose too much) to get any kind of handle on the management.
I've never liked 'go do what you do, or don't, I don't care' methods, especially when there may be a dramatic performance hit, or even VM-wide freeze-up for a second or two in a busy system... (Witness numerous Swing apps where the fashion is to do System.gc() on certain menu commands).
Ross
 Signature [Ross A. Bamford] [ross AT the.website.domain] Roscopeco Open Tech ++ Open Source + Java + Apache + CMF http://www.roscopec0.f9.co.uk/ + info@the.website.domain
krasicki - 16 May 2005 03:20 GMT > > -snip- -all good comments - > [quoted text clipped - 9 lines] > > Other than that, try to prefer an instance method of an object. - snip -
Yes. This is really the crux of the argument. This is procedural stuff poking its way into OO territory and i always get the feeling that people doing it get a secret pleasure out of it - like kicking a vending machine.
Ross Bamford - 13 May 2005 12:39 GMT > As a rule of thumb, would I be correct in suggesting that factory > methods should be static when they serve the broadest utilitarian [quoted text clipped - 4 lines] > After all, this technique seems to violate strict object-oriented > implementation practice. Factory methods are great where you want a singleton:
public class ServiceProvider { private static final ServiceProvider prov = new ServiceProvider(class.getResourceAsStream("sp.xml"));
private ServiceProvider(InputStream XML) { // ... Configure from XML ... }
public Degigitator doService(Rerulurator r) { // ... service according to config ... }
// Factory public static ServiceProvider getInstance() { return prov; } }
This is ideal for stuff you want global, since there will be only one instance per JVM, and you can get it from anywhere:
myDegig = ServiceProvider.getInstance().doService(myRulurator));
If your needs are more complex, you could have a static factory that creates instance factories with a certain configuration. In this situation I often define an abstract class as the factory 'interface', and provide on that the static factory.
Handy uses are many: SPI, Registry, logging (in small apps), etc, etc, etc. It does require a little more consideration of the runtime lifecycle of the JVM, and there are one or two nasty gotchas (as always) but generally it's a useful technique (that seems to be going out of fashion now in favour of context-scoped 'singletons').
Cheers, Ross
 Signature [Ross A. Bamford] [ross AT the.website.domain] Roscopeco Open Tech ++ Open Source + Java + Apache + CMF http://www.roscopec0.f9.co.uk/ + info@the.website.domain
Wibble - 14 May 2005 00:27 GMT Stop looking for stupid rules and do what makes sense. The rules I use when programming java are:
You arent gonna need it.
Do the simplest thing that can possibly work.
(Yeah, I stole them from Beck)
If you NEED a factory for a reason, create one, otherwise dont. If you dont understand why you need one, you dont need one.
>>As a rule of thumb, would I be correct in suggesting that factory >>methods should be static when they serve the broadest utilitarian [quoted text clipped - 44 lines] > Cheers, > Ross Ross Bamford - 14 May 2005 04:01 GMT > <fixed toppost>
> >>As a rule of thumb, would I be correct in suggesting that factory > >>methods should be static when they serve the broadest utilitarian [quoted text clipped - 57 lines] > dont. If you dont understand why you need one, you dont > need one. You know, you can actually do most stuff by stringing commands together with a shell. That way, you don't need to worry about the bytecode interpreter, runtime, factories, classes, instantiation, oop, methods, or any of that other stupid advanced crap.
Ross
 Signature [Ross A. Bamford] [ross AT the.website.domain] Roscopeco Open Tech ++ Open Source + Java + Apache + CMF http://www.roscopec0.f9.co.uk/ + info@the.website.domain
Andrew McDonagh - 14 May 2005 20:10 GMT > I had never run into this before but have recently encountered code > that is something like: [quoted text clipped - 20 lines] > Disclaimer: YES,YES,YES - I know, I know... but take it for what it's > worth. Actually just realised something that may help you - or confuse you completely... ;-)
Seeing as the only way to start a java application is via a class's 'main method.
class HelloWorldApp {
public static void main(String[] args) { Message m = new Message(); m.show(); } }
class Message {
public void show() { String theMessage = "Hello world"; System.out.println(theMessage); }
Seeing as this is the case, just about every single object created by the application, will have some relationship to the static main method.
In the case above, the message object referenced by 'm', has been created by the 'main' method. It in turns creates the String object referenced by 'theMessage'.
if it was a GUI app, then we could have created a dialog, with various components inside the 'show()' method, and so the tree of related objects would grow even larger.
Does this help show that creating objects and static methods have no baring upon each other and so how the GC works with those objects?
Nick Malik [Microsoft] - 15 May 2005 08:23 GMT Has it occurred to you that the problem isn't the return of the newly created object, but perhaps it's in the section you labeled 'yada yada'?
> public static MyWidget staticMethod() { > // yada yada > return new MyWidgetObject(); > } Caveat: I'm not a Java developer. If I say something goofy, please forgive.
Are you creating other things, or manipulating static variables in your class (or calling another static method on this or another class that manipulates heap memory) during this 'yada yada'? The problem may be that these memory locations are shared between threads. Could you be running into concurrency issues where you have referenced a shared value without considering the thread-safety of these values?
 Signature --- Nick Malik [Microsoft] MCSD, CFPS, Certified Scrummaster http://blogs.msdn.com/nickmalik
Disclaimer: Opinions expressed in this forum are my own, and not representative of my employer. I do not answer questions on behalf of my employer. I'm just a programmer helping programmers. --
krasicki - 16 May 2005 02:46 GMT Nick,
Sorry, no hidden gotchas. I was on my way to my son's Pony League baseball game and was being as straightforward and brief as could be.
However, much of the surrounding code is ugly in a juvenile way which is why I questioned this technique. I'm guessing whoever wrote the stuff remembered a shortcut but didn't pay attention to elementary things like if-then-else (I have multiple if statements on after another (lots 'o them) in a while loop.
This onion would make you all cry.
Thanks, Nick - I hear you and you're correct in asking but what prompted my questrion was my inability to find good literature on this specific subject. I'm being intentionally belligerent to shake it all out well so that others looking for a comprehensive treatment might get it here.
Everyone responding has been great and the thread, IMO, is worth a read.
cheers,
Frank
> Has it occurred to you that the problem isn't the return of the newly
> created object, but perhaps it's in the section you labeled 'yada yada'? > [quoted text clipped - 7 lines] > Are you creating other things, or manipulating static variables in your > class (or calling another static method on this or another class that
> manipulates heap memory) during this 'yada yada'? The problem may be that > these memory locations are shared between threads. Could you be running [quoted text clipped - 11 lines] > programmer helping programmers. > -- Tony Morris - 15 May 2005 09:53 GMT This is the correct way to expose construction of objects. Non-private constructors violate encapsulation. If only this very fundamental, simple and obvious concept was taught from the beginning. Book containing explanation pending...
 Signature Tony Morris Software Engineer, IBM Australia. BInfTech, SCJP 1.4, SCJP 5.0, SCJD
http://www.jtiger.org/ JTiger Unit Test Framework for Java http://qa.jtiger.org/ Java Q&A (FAQ, Trivia) http://xdweb.net/~dibblego/
krasicki - 16 May 2005 02:35 GMT > This is the correct way to expose construction of objects. Don't you mean 'A' correct way.
> Non-private constructors violate encapsulation. I'm not sure where you're going here.
> If only this very fundamental, simple and obvious concept was taught from > the beginning. > Book containing explanation pending... Tony, you're awfully sparse on words here.
> -- > Tony Morris [quoted text clipped - 4 lines] > http://qa.jtiger.org/ Java Q&A (FAQ, Trivia) > http://xdweb.net/~dibblego/ Tony Morris - 16 May 2005 13:12 GMT > > This is the correct way to expose construction of objects. > > Don't you mean 'A' correct way. No.
> > Non-private constructors violate encapsulation. > > I'm not sure where you're going here. Think about it - it's not a secret (that is, I didn't dream it up - it's a fundamental fact known to all practising purists).
> > If only this very fundamental, simple and obvious concept was taught > from > > the beginning. > > Book containing explanation pending... > > Tony, you're awfully sparse on words here. I intended only to provoke thought on behalf of the reader, not write the book.
> > -- > > Tony Morris [quoted text clipped - 4 lines] > > http://qa.jtiger.org/ Java Q&A (FAQ, Trivia) > > http://xdweb.net/~dibblego/
 Signature Tony Morris Software Engineer, IBM Australia. BInfTech, SCJP 1.4, SCJP 5.0, SCJD
http://www.jtiger.org/ JTiger Unit Test Framework for Java http://qa.jtiger.org/ Java Q&A (FAQ, Trivia) http://xdweb.net/~dibblego/
Tor Iver Wilhelmsen - 16 May 2005 19:07 GMT > Think about it - it's not a secret (that is, I didn't dream it up - it's a > fundamental fact known to all practising purists). Since a lot of programmers disagree with you (ie. they think that constructors can be non-private), calling it a "fundamental fact" makes you look like an arrogant snob.
Tony Morris - 17 May 2005 09:37 GMT > > Think about it - it's not a secret (that is, I didn't dream it up - it's a > > fundamental fact known to all practising purists). > > Since a lot of programmers disagree with you (ie. they think that > constructors can be non-private), calling it a "fundamental fact" > makes you look like an arrogant snob. Perhaps so, but I have no qualms with that - the truth is of far more importance than mere ego attacks. Copernicus looked like one of those too, before the Earth orbitted the Sun.
 Signature Tony Morris Software Engineer, IBM Australia. BInfTech, SCJP 1.4, SCJP 5.0, SCJD
http://www.jtiger.org/ JTiger Unit Test Framework for Java http://qa.jtiger.org/ Java Q&A (FAQ, Trivia) http://xdweb.net/~dibblego/
Rich MacDonald - 17 May 2005 23:06 GMT > practising purists Mutually incompatible.
Joona I Palaste - 16 May 2005 21:50 GMT Tony Morris <not@telling.you> scribbled the following on comp.lang.java.programmer:
> This is the correct way to expose construction of objects. > Non-private constructors violate encapsulation. > If only this very fundamental, simple and obvious concept was taught from > the beginning. > Book containing explanation pending... I'd love to see that book of yours. I know something about Java, but I can't think of any useful way to create new objects in Java without using non-private constructors at some point. Unless you want to use the static factory pattern in *every* class, which I find ugly.
 Signature /-- Joona Palaste (palaste@cc.helsinki.fi) ------------- Finland --------\ \-------------------------------------------------------- rules! --------/ "I am lying." - Anon
Tony Morris - 17 May 2005 09:42 GMT > Tony Morris <not@telling.you> scribbled the following > on comp.lang.java.programmer: [quoted text clipped - 8 lines] > non-private constructors at some point. Unless you want to use the > static factory pattern in *every* class, which I find ugly. The book is currently a set of scribble notes in a A4 pad. I make no promises, but I do beg of you, please think about it some more - it is blatantly obvious to any "practising purist". That is to say, ask anyone else who is also part of this minority group and they might provide a peek into the persecptive I speak of. I dare not for fear of undermining the entire point, hence I intend (actually, I 'hope') to cover it in full some day. An example of undermining the points is the article written by Holub titled 'Why extends is evil'. Any practising purist also knows that concrete inheritance implies a flawed design (yes, always), but Holub makes the point in a horrible way. I have refuted this article in somewhat minor detail (again, due to the aforementioned apprehension) here: http://www.jtiger.org/articles/why-extends-is-not-evil.html
 Signature Tony Morris Software Engineer, IBM Australia. BInfTech, SCJP 1.4, SCJP 5.0, SCJD
http://www.jtiger.org/ JTiger Unit Test Framework for Java http://qa.jtiger.org/ Java Q&A (FAQ, Trivia) http://xdweb.net/~dibblego/
Ross Bamford - 17 May 2005 16:50 GMT > > Tony Morris <not@telling.you> scribbled the following > > on comp.lang.java.programmer: [quoted text clipped - 24 lines] > aforementioned apprehension) here: > http://www.jtiger.org/articles/why-extends-is-not-evil.html Nice one Tony :) The original /is/ somewhat inflammatory ;) Out of interest, have a quick look at some of the dependency injection stuff around now, which I think has the potential to remedy the situation if used properly. Particularly with respect to implementation hiding and encapsulation. The goal for my current project is to be based entirely around interfaces, with implementations being dynamically registered and selected from those available to fit the need of another.
The only thing I would say is that final classes, while preventing concrete inheritance, also prevents lots of clever stuff like dynamic proxy classes and stuff, which helps make the above possible. Another solution might be to simply remove it from the language, along with making 'extends' illegal on classes. ;)
Cheers, Ross
 Signature [Ross A. Bamford] [ross AT the.website.domain] Roscopeco Open Tech ++ Open Source + Java + Apache + CMF http://www.roscopec0.f9.co.uk/ + info@the.website.domain
Tony Morris - 17 May 2005 22:16 GMT > > > Tony Morris <not@telling.you> scribbled the following > > > on comp.lang.java.programmer: [quoted text clipped - 41 lines] > Cheers, > Ross Indeed, hence for some frameworks, such as Hibernate that use dynamic proxying, the best I can do is declare the class non-final and declare all methods final (including, unfortunately, those of java.lang.Object). I agree that dependency injection is one solution, though I'm not prepared to say that it is the solution. A language fix would solve it, and the abolishment of extends on concrete types is certainly better than my suggested 'convention', but even so, that's a workaround and you are forever tied to concrete inheritance (java.lang.Object). Only a breaking on reverse compatibility will ultimately fix it (a new language perhaps?)
Here are some thoughts: - Swing is the most difficult of APIs to write unit tests for, and it is also the core API that has the strongest dependancy on concrete inheritance. - Whever you cannot achieve 100% coverage of your code due to test, it is always because of concrete inheritance. That is to say, without concrete inheritance, you can always achieve 100% coverage. If you cannot achieve 100% coverage, then why does the code exist? The test code is, after all, the client. - JTiger (http://www.jtiger.org/) achieves 100% class and 100% method coverage, however, outright 100% coverage cannot be achieved in cases where a third party dependancy exists since concrete inheritance is used e.g. Ant task, JavaBeans, Java exceptions (all three of these mandate concrete inheritance directly or indirectly). In all other cases, 100% coverage is achieved. It is in these circumstance only where a trade-off is justified (e.g. shall I rewrite Ant/JavaBeans/the Java language properly, or concede and use concrete inheritance and expose a constructor in my types? I chose the latter for obvious reasons). JTiger declares all classes final (hiding the dependancy on concrete inheritance, but not exposing it itself).
I just realised I have gone from "constructors violate encapsulation to concrete inheritance violates encapsulation", but the two assertions are intrinsically related. Still, what do you mean inflammatory? What exactly?
Tony Morris Software Engineer, IBM Australia. BInfTech, SCJP 1.4, SCJP 5.0, SCJD
http://www.jtiger.org/ JTiger Unit Test Framework for Java http://qa.jtiger.org/ Java Q&A (FAQ, Trivia) http://xdweb.net/~dibblego/
Lee Fesperman - 18 May 2005 20:16 GMT > > > > Tony Morris <not@telling.you> scribbled the following > > > > on comp.lang.java.programmer: [quoted text clipped - 59 lines] > > Roscopeco Open Tech ++ Open Source + Java + Apache + CMF > > http://www.roscopec0.f9.co.uk/ + info@the.website.domain --- retained for reasons explained below ---
> - Whever you cannot achieve 100% coverage of your code due to test, it is > always because of concrete inheritance. That is to say, without concrete > inheritance, you can always achieve 100% coverage. If you cannot achieve > 100% coverage, then why does the code exist? The test code is, after all, > the client. I can't believe you're claiming that one can have 100% test coverage except for the most trivial of applications. Then, you claim that concrete inheritance is the only reason 100% can't be achieved. What about multithreading, customer input, GUI complications?
> - JTiger (http://www.jtiger.org/) achieves 100% class and 100% method > coverage, however, outright 100% coverage cannot be achieved in cases where [quoted text clipped - 6 lines] > the latter for obvious reasons). JTiger declares all classes final (hiding > the dependancy on concrete inheritance, but not exposing it itself). Oh, now I see, you're touting unit test software. I think everyone will need to take your pronouncements with a grain of salt.
> I just realised I have gone from "constructors violate encapsulation to > concrete inheritance violates encapsulation", but the two assertions are > intrinsically related. > Still, what do you mean inflammatory? What exactly? While there is some general agreement that concrete inheritance can be problematic, you seem to be the only one claiming it is always wrong. I'm afraid your supporting comments on that tack are vague. Get off your soapbox and write your book ;^)
BTW, you've also fallen back into bad quoting style. Please trim signatures when you quote, please.
 Signature Lee Fesperman, FFE Software, Inc. (http://www.firstsql.com) ============================================================== * The Ultimate DBMS is here! * FirstSQL/J Object/Relational DBMS (http://www.firstsql.com)
krasicki - 18 May 2005 04:11 GMT > Tony Morris <not@telling.you> scribbled the following > on comp.lang.java.programmer: [quoted text clipped - 8 lines] > non-private constructors at some point. Unless you want to use the > static factory pattern in *every* class, which I find ugly. Joona, here's the chapter he's looking for;
http://today.java.net/pub/a/today/2005/04/14/dependency.html
Tony Morris - 18 May 2005 06:04 GMT > > Tony Morris <not@telling.you> scribbled the following > > on comp.lang.java.programmer: [quoted text clipped - 15 lines] > > http://today.java.net/pub/a/today/2005/04/14/dependency.html At first glance, that looks to me like the strategy design pattern reiteratively re-explained explained again. This is related to the fundamental rule that the use of Java switch/case can never be justified (no, not even in 1.5) :) Should I shut up or give reasons why I don't want to justify that too? The article provides a half-arsed explanation - the audience should get the gist.
 Signature Tony Morris Software Engineer, IBM Australia. BInfTech, SCJP 1.4, SCJP 5.0, SCJD
http://www.jtiger.org/ JTiger Unit Test Framework for Java http://qa.jtiger.org/ Java Q&A (FAQ, Trivia) http://xdweb.net/~dibblego/
John C. Bollinger - 17 May 2005 18:26 GMT > This is the correct way to expose construction of objects. > Non-private constructors violate encapsulation. > If only this very fundamental, simple and obvious concept was taught from > the beginning. This assertion is certainly simple to _express_, but it's correctness is not obvious, at least to me. That being the case, I sincerely doubt whether it is simple to explain or justify.
> Book containing explanation pending... That book seems always to be pending. It's the same one, I presume, where you are going to discuss why you say all classes should be either abstract or final? I at least have less trouble imagining possible arguments for that one.
Any way around, it adds nothing useful to the discussion to make controversial assertions and then duck all attempts to engage you in any debate about them. Appeal to the authority of a nonexistent book in no way supports your claims. When the book appears, however, let us know.
 Signature John Bollinger jobollin@indiana.edu
Tony Morris - 17 May 2005 22:20 GMT > > This is the correct way to expose construction of objects. > > Non-private constructors violate encapsulation. [quoted text clipped - 11 lines] > abstract or final? I at least have less trouble imagining possible > arguments for that one. No, always final.
> Any way around, it adds nothing useful to the discussion to make > controversial assertions and then duck all attempts to engage you in any > debate about them. Appeal to the authority of a nonexistent book in no > way supports your claims. When the book appears, however, let us know. Agreed, I try to shut up, but it slips out every now and then and goes far beyond the intended course. Still, I maintain that if you (or anyone) has the right to suggest that, for example, "you should inherit from this class" on no sound basis (which I claim does not exist even if it were attempted), I also maintain the right to say, "no, do not inherit from this class" (on a basis that I claim exists and I *know* exists without doubt - at least in my mind).
 Signature Tony Morris Software Engineer, IBM Australia. BInfTech, SCJP 1.4, SCJP 5.0, SCJD
http://www.jtiger.org/ JTiger Unit Test Framework for Java http://qa.jtiger.org/ Java Q&A (FAQ, Trivia) http://xdweb.net/~dibblego/
Dale King - 18 May 2005 05:07 GMT >>>This is the correct way to expose construction of objects. >>>Non-private constructors violate encapsulation. [quoted text clipped - 24 lines] > Agreed, I try to shut up, but it slips out every now and then and goes far > beyond the intended course. Well, saying that it is "obvious" when it is not obvious to those here is not an effective way of shutting up. You basically are insulting anyone that disagrees with you.
> Still, I maintain that if you (or anyone) has the right to suggest that, for > example, "you should inherit from this class" on no sound basis (which I > claim does not exist even if it were attempted), I also maintain the right > to say, "no, do not inherit from this class" (on a basis that I claim exists > and I *know* exists without doubt - at least in my mind). It seems to me that you have two assertions that you are trying to merge into one and I fail to see how they are related. The assertions I see are:
- Concrete inheritance is evil - Constructors should be private
Even if one agreed with the first one the second one does not follow from the first. Even with no concrete inheritance you still need a way to create concrete instances.
For the first I would agree that concrete inheritance is quite often abused and should be used less that it is, I do not agree that it is always evil. For one thing every class in Java uses concrete inheritance. Every object inherits some concrete implementations from Object.
I find very little justification for your second assertion and you have offered none.
 Signature Dale King
Tony Morris - 18 May 2005 05:59 GMT > >>>This is the correct way to expose construction of objects. > >>>Non-private constructors violate encapsulation. [quoted text clipped - 28 lines] > is not an effective way of shutting up. You basically are insulting > anyone that disagrees with you. I'm assuming that the doctrine is merely being iterated as fundamental fact without any thought. With a completely open mind, it is obvious, at least, to me. No insult is intended.
> > Still, I maintain that if you (or anyone) has the right to suggest that, for > > example, "you should inherit from this class" on no sound basis (which I [quoted text clipped - 11 lines] > from the first. Even with no concrete inheritance you still need a way > to create concrete instances. They are very much related, but again, I'm being torn between 'shutting up' and writing a book chapter. I dare not fall somewhere in between for fear of undermining the truth and potentially confusing an audience.
> For the first I would agree that concrete inheritance is quite often > abused and should be used less that it is, I do not agree that it is > always evil. For one thing every class in Java uses concrete > inheritance. Every object inherits some concrete implementations from > Object. Yes, Java is intrincisally flawed. I intend to offer alternatives to concrete inheritance, including the special case of java.lang.Object (which ties the language spec., not just the API spec., to concrete inheritance). The only justification for concrete inheritance is where a third party dependancy exists - should you reimplement that dependancy (in this case, the Java programming language) or concede to the brokenness? In cases where you concede, I intend to provide a neat solution (isolating the brokenness). You would concede in some cases because of a trade-off; sure, reimplementing Java is extreme and reality is reality. It certainly pays to acknowledge that it exists though. For the case of concrete inheritance without a third party depend
|
|