finalize() not guaranteed to be called -- ever

R

Raymond DeCampo

Dale said:
Which is not really that different from C++. C++ destructors are invoked
manually as well by calling delete.

That is true only in the case where the objects were created with the
new operator. For object constructed in the standard way, the
destructor is invoked by the compiler when the variable goes out of
scope. (Please excuse the slightly sloppy language.)

Ray
 
P

Paul J. Lucas

Dale King said:
Java puts all objects on the heap, so objects never have a scope. The way to
make sure something gets cleaned up at the end of a scope in Java is to use a
try-finally block. It is a little more manual, but since Java only needs to
do this for non-memory resources it is not that common and generally only
needs to occur for files, DB connections, etc.

Perhaps not in the code you write. But most any useful program
has to get data from someplace and/or put it someplace else,
i.e., interact with stuff "out there" via things like files and
DB connections.

The use of try/finally is:

+ easily forgotten
+ easy to get wrong
+ tedious to write

Java eliminates most memory-management concerns and errors, but
the price you pay is now having to worry about other kinds of
resources that Java gives you *zero* help with. It's funny how
that's never mentioned by the Java/Sun marketing literature.
[finalize] is not guaranteed to ever occur, but some safety net is better
than no safety net.

I don't particulary care for Heisenberg programming.

- Paul
 
D

Dale King

Roedy said:
The Jet compiler puts some objects on the stack so they automatically
are gced when they go out of scope. The JVM has so such provision,
but the language itself is flexible enough to accommodate it.

Conceptually, such a thing does not exist in Java even if it does in
practice as an optimisation.

The generational garbage collector in the current JVM also uses a stack,
but it is seperate from the execution stack. Objects are allocated on
this stack called the nursery. When the nursery is filled objects that
are still "live" are moved to the heap. It gives you the same advantage
of the stack implementation you talk about that short lived objects are
cheap.
 
D

Dale King

Raymond said:
That is true only in the case where the objects were created with the
new operator. For object constructed in the standard way, the
destructor is invoked by the compiler when the variable goes out of
scope. (Please excuse the slightly sloppy language.)

But Java only creates objects on the heap. It has no variables that
actually hold objects. Therefore there is no such thing as scope for
objects.
 
C

Chris Uppal

Dale said:
The generational garbage collector in the current JVM also uses a stack,
but it is seperate from the execution stack. Objects are allocated on
this stack called the nursery.

Dale, I suspect you know all the following, but your expression above it quite
misleading if taken at face value, so for the record...

Unless the Sun implementation is /very/ different from a standard nursery-space
implementation (which it might be, but I doubt it, and have seen no evidence
for it), then the nursery is not a stack. For allocation it works in roughly
the same way as a stack would (i.e it grows linearly and cheaply), but
"deallocation" is handled differently since it does not shrink when the
execution stack shrinks (and I would say that shrinking is one of the defining
qualities of any "stack").

Jet presumably does some sort of capture analysis at compile time in order to
see which created objects are only referred to by varaible that go out of scope
when a method returns. That would allow them to allocate those object directly
on the stack /and/ have them reclaimed automatically as the method returns.

-- chris
 
R

Raymond DeCampo

Dale said:
But Java only creates objects on the heap. It has no variables that
actually hold objects. Therefore there is no such thing as scope for
objects.

Two points. First, I was primarily addressing the fact that the
statement "C++ destructors are invoked manually...by calling delete" is
not entirely accurate. What Java does or does not do is irrelevant to
this fact.

Second, when comparing C++ and Java you cannot discount an advantage of
C++ by saying that Java has no appropriate analog. Destructors are a
nice feature of C++. The designers of Java could have chosen to add
them to the language, but decided not to. (It could very well be that
the implications of having destructors affected other things like
garbage collection in negative ways and this was a wise decision. I
don't know nor am I passing judgment.)

If my second point does not address your point, you'll have to make your
point clearer to me, because I am missing it.

Ray
 
D

Dale King

Chris said:
Dale King wrote:



Dale, I suspect you know all the following, but your expression above it quite
misleading if taken at face value, so for the record...

Unless the Sun implementation is /very/ different from a standard nursery-space
implementation (which it might be, but I doubt it, and have seen no evidence
for it), then the nursery is not a stack. For allocation it works in roughly
the same way as a stack would (i.e it grows linearly and cheaply), but
"deallocation" is handled differently since it does not shrink when the
execution stack shrinks (and I would say that shrinking is one of the defining
qualities of any "stack").

And the fact that it does not pop them one at a time does not mean it is
not like a stack. It is like a stack that you push new objects into.
When it is full it empties the whole stack.

It is not just me that say that it is like a stack. The Sun white paper
that describes it says

"...new objects are allocated contiguously in stack-like fashion in the
object nursery"
 
D

Dale King

Raymond said:
Two points. First, I was primarily addressing the fact that the
statement "C++ destructors are invoked manually...by calling delete" is
not entirely accurate. What Java does or does not do is irrelevant to
this fact.

No, it is entirely accurate. Notice I did not say they are *only* called
manually.
Second, when comparing C++ and Java you cannot discount an advantage of
C++ by saying that Java has no appropriate analog. Destructors are a
nice feature of C++. The designers of Java could have chosen to add
them to the language, but decided not to. (It could very well be that
the implications of having destructors affected other things like
garbage collection in negative ways and this was a wise decision. I
don't know nor am I passing judgment.)

If my second point does not address your point, you'll have to make your
point clearer to me, because I am missing it.

For objects allocated on the heap there really is no big difference from
C++ and Java. The destruction is still a manual process. In C++ you call
delete for every object created. In Java you call a dispose method which
you only have to do for objects with non-memory resources to free.

C++ has the added feature that objects can be created as local variables
which are destroyed automatically when the variable goes out of scope.
And Java does not have this feature nor manual forced deletion of the
object because they lead to things like dangling pointers. The other
problem is that objects in variables have value semantics and not
reference semantics. Value semantics for an object means that the object
will not be polymorphic. It can also cause confusion when you do
something like this where B is a subclass of A:

B b;
A a = b;

Which will cause a to not be a B anymore.

So the point is that the issue has nothing to do with destructors, but
with the lack of variables that hold objects. Just adding destructors
buys you absolutely nothing for Java.
 
R

Raymond DeCampo

Dale said:
No, it is entirely accurate. Notice I did not say they are *only* called
manually.

The context of the original quote (which I inadvisable snipped) did have
the connotation of "only", in that you were comparing them to a scheme
in Java where close() or release() type methods were invoked. The only
way to do this in Java is manually and you said this "not that different
from C++". It is very different in that it is possible to write C++
programs in which the destructors are never invoked manually but do run.
This is not possible in Java.

In any case, I do not want to get into a word parsing you said/I said
match. I just want to make it clear that C++ destructors are not solely
invoked manually and have no comparable mechanism in Java. My apologies
if I misunderstood your post.
For objects allocated on the heap there really is no big difference from
C++ and Java. The destruction is still a manual process. In C++ you call
delete for every object created. In Java you call a dispose method which
you only have to do for objects with non-memory resources to free.

There is a much bigger difference than you represent. In C++ you *must*
manually delete objects created via new or you get a memory leak.
Objects in Java do not *necessarily* have a method that must be called
to release resources.
C++ has the added feature that objects can be created as local variables
which are destroyed automatically when the variable goes out of scope.

Right; the real point however is that creating local variables is
standard operating procedure in C++ while it is not possible in Java.
So in C++ developers have the option of using local variables and
getting the destructors invoked "for free". This option is not
available in Java, as you note below.

And Java does not have this feature nor manual forced deletion of the
object because they lead to things like dangling pointers. The other
problem is that objects in variables have value semantics and not
reference semantics. Value semantics for an object means that the object
will not be polymorphic. It can also cause confusion when you do
something like this where B is a subclass of A:

B b;
A a = b;

Which will cause a to not be a B anymore.

You'll have to be more clear here. I'm not even certain which language
you are referring to.
So the point is that the issue has nothing to do with destructors, but
with the lack of variables that hold objects. Just adding destructors
buys you absolutely nothing for Java.

I do not see how your conclusion follows. Destructors could be added to
Java with benefits. All that would really be necessary would be that
the JVM should guarantee that finalize() is called. Then
implementations of java.sql.Connection could close() themselves, etc.
There are many pitfalls there however and the designers of Java chose
not to include this benefit. To say it buys you nothing doesn't wash
however.

Ray
 
C

Chris Smith

Raymond DeCampo said:
You'll have to be more clear here. I'm not even certain which language
you are referring to.

Dale is referring to C++, and explaining very succinctly why "objects"
placed on the stack in C++ are NOT actually objects by the standards of
typical OO theory. It's a point that's lost on many C++ developers. It
is also the justification for not including this possibility in Java.
I do not see how your conclusion follows. Destructors could be added to
Java with benefits. All that would really be necessary would be that
the JVM should guarantee that finalize() is called. Then
implementations of java.sql.Connection could close() themselves, etc.

Let's start by agreeing on common definitions. A destructor a block of
code that is called automatically when an object is deallocated. Since
there's never any way at all to guarantee that an object will be
deallocated in Java, destructors per se wouldn't do any good.

You suggest that the JVM can just guarantee that finalize() is called,
without changing the memory model. The question is: WHEN would the JVM
guarantee to do that?

Would it be called whenever ANY reference to an object goes out of
scope? That would be very annoying, and would entirely prevent such
basic and good design techniques as passing database connections to
other methods or storing them in data structures. They would be getting
inadvertently closed all the time, and oh what a pain it would be.

Would it be called whenever the last live reference to an object goes
out of scope? I hope not, because that would prevent the use of any
kind of deferred garbage collection algorithms for finalizable objects.
You'd be stuck with all JVMs doing weak/strong ref-counting for ANY
reference to ANY supertype of ANY type that defines a finalize() method.
Performance would tank, and we'd be in serious trouble.

Or perhaps the VM should read your mind and decide when to call the
destructor?
There are many pitfalls there however and the designers of Java chose
not to include this benefit. To say it buys you nothing doesn't wash
however.

Dale said it doesn't buy you anything unless you also change the memory
model to allow locally-scoped "objects" (which, of course, are not true
objects). As it turns out, Dale hit it right on the head on this one.
I'm anxiously awaiting your answer to the magic question of "when", as
explained above.

--
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
C

Chris Smith

Dale King said:
And the fact that it does not pop them one at a time does not mean it is
not like a stack. It is like a stack that you push new objects into.
When it is full it empties the whole stack.

It is not just me that say that it is like a stack. The Sun white paper
that describes it says

"...new objects are allocated contiguously in stack-like fashion in the
object nursery"

I'm with Chris here. Just because someone writes something doesn't make
it true, even if that someone works for Sun. The person who wrote the
comment above is taking one INCIDENTAL implementation detail of only ONE
instance of the use of stacks, and confusing it with the concept of a
stack. That person is either demonstrating their lack of a reasonable
theoretical grounding in computer science, or trying too hard at writing
for people who lack said grounding. In either case, it doesn't seem
like a good model for behavior.

The one and only defining characteristic of a stack is LIFO. It doesn't
make to say that something is "like a stack" except that it isn't LIFO.
Might as well say that a color is just like green except that it is red;
or that someone looks Chinese except for the fair skin, blond hair, and
blue eyes.

--
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
D

Dale King

Chris said:
I'm with Chris here. Just because someone writes something doesn't make
it true, even if that someone works for Sun. The person who wrote the
comment above is taking one INCIDENTAL implementation detail of only ONE
instance of the use of stacks, and confusing it with the concept of a
stack. That person is either demonstrating their lack of a reasonable
theoretical grounding in computer science, or trying too hard at writing
for people who lack said grounding. In either case, it doesn't seem
like a good model for behavior.

The one and only defining characteristic of a stack is LIFO. It doesn't
make to say that something is "like a stack" except that it isn't LIFO.
Might as well say that a color is just like green except that it is red;
or that someone looks Chinese except for the fair skin, blond hair, and
blue eyes.

As I have said many times before I hate Usenet arguments that boil down
to arguments over definitions. Particularly when we agree on the facts,
just not the words you apply to them.

The nursery is like a subset of a stack. There is nothing inconsistent
with a stack. Allocation is just like a stack. It just never pulls items
out of the stack. If you have a more precise term feel free to suggest it.
 
C

Chris Uppal

Dale said:
[me:]
Unless the Sun implementation is /very/ different from a standard
nursery-space implementation (which it might be, but I doubt it, and
have seen no evidence for it), then the nursery is not a stack. For
allocation it works in roughly the same way as a stack would (i.e it
grows linearly and cheaply), but "deallocation" is handled differently
since it does not shrink when the execution stack shrinks (and I would
say that shrinking is one of the defining qualities of any "stack").

And the fact that it does not pop them one at a time does not mean it is
not like a stack. It is like a stack that you push new objects into.
When it is full it empties the whole stack.

This is disingenuous. It is /not/ like a stack in any significant way. There
is no storage management system that I am aware of that does not (in some
more-or-less straightforward sense) allocate storage linearly in many
situations, but few of them are even remotely stack like. The /defining
characteristic/ of stack-like allocation is that storage is reclaimed on a LIFO
basis. That is the /only/ interesting characteristic that justifies the use of
the word "stack" (in discussions of storage management algorithms). In
particular, a LIFO storage reclamation strategy has certain operational
characteristics that are highly desirable if they can be achieved. The
GC-based storage allocation strategy of Java does not have those
characteristics. Calling it "stack like" is simply misleading.

It is not just me that say that it is like a stack. The Sun white paper
that describes it says

"...new objects are allocated contiguously in stack-like fashion in the
object nursery"

Well, I have no wish (at all !) to accuse /you/ of dishonesty, but if Sun have
written that then the only explanation I can see is that they are actively
attempting to mislead their readers. Maybe the paper was only written with an
overzealous urge to (over)simplify, but without having read the rest of the
paper it sounds like a straightforward lie to me.

-- chris
 
C

Chris Uppal

Dale said:
As I have said many times before I hate Usenet arguments that boil down
to arguments over definitions. Particularly when we agree on the facts,
just not the words you apply to them.

"When /I/ use a word," Humpty Dumpty said in a rather scornful tone, "it means
just what I choose it to mean -- neither more nor less."

-- chris
 
T

Thomas Hawtin

Chris said:
This is disingenuous. It is /not/ like a stack in any significant way. There

In a traditional system allocation comes down to either linearly on the
stack or free lists on the heap. No one is claiming that eden is a
stack, but allocating linearly is more stack allocation-like than it is
like tradition heap allocation. At least in terms of allocation
algorithm and performance.
is no storage management system that I am aware of that does not (in some
more-or-less straightforward sense) allocate storage linearly in many
situations, but few of them are even remotely stack like. The /defining

Almost always they are reallocating previously freed memory. Usually
trying to match a similar size fragment. Sometimes dividing larger
sections, but rarely taking incremental junks out of big pie.
characteristic/ of stack-like allocation is that storage is reclaimed on a LIFO
basis. That is the /only/ interesting characteristic that justifies the use of
the word "stack" (in discussions of storage management algorithms). In

To say A is like, or has similarities with, B does not imply they share
any definition. When comparing instances of things, lawyer-like
comparisons of definitions are not helpful.

Tom Hawtin
 
C

Chris Smith

Chris Uppal said:
Well, I have no wish (at all !) to accuse /you/ of dishonesty, but if Sun have
written that then the only explanation I can see is that they are actively
attempting to mislead their readers. Maybe the paper was only written with an
overzealous urge to (over)simplify, but without having read the rest of the
paper it sounds like a straightforward lie to me.

I'm pretty sure it's not supposed to be a lie. I'd bet money that the
person writing that paper was simply saying that the primary path for
allocation in the Java nursery follows an identical sequence of steps to
the primary path for allocation of a stack frame in a typical
implementation of stack-based storage on a typical computer
architecture. Namely, it goes like this: bump a pointer, compare
against a boundary, and consider the space allocated iff the pointer is
within the boundary.

Of course, there are two major problems here. First, no mention is made
of the complementary process of removing data from the structure, which
differs radically. Second, there's no mention of the three qualifying
conditions: 1) Only the fast/primary paths are considered, 2) typical
implementation, and 3) typical computer architecture. Don't get me
wrong here. I agree that it's misleading... but I really doubt it's
dishonest.

--
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
D

Dale King

Chris said:
Well, I have no wish (at all !) to accuse /you/ of dishonesty, but if Sun have
written that then the only explanation I can see is that they are actively
attempting to mislead their readers. Maybe the paper was only written with an
overzealous urge to (over)simplify, but without having read the rest of the
paper it sounds like a straightforward lie to me.

I don't think it is mileading at all. New objects are in fact allocated
contiguously in stack-like fashion in the object nursery. I fail to see
anything that is not factually true in that statement. It gives a
picture that most programmers understand, namely that you allocate
simply by bumping a pointer.

I agree that I was being imprecise in *my* statement where I called the
nursery a stack, but the Sun statement is in fact true and not misleading.
 
D

Dale King

Raymond said:
The context of the original quote (which I inadvisable snipped) did have
the connotation of "only",

That connotation is only in your imagination because it was not there in
what I wrote.
in that you were comparing them to a scheme
in Java where close() or release() type methods were invoked. The only
way to do this in Java is manually and you said this "not that different
from C++". It is very different in that it is possible to write C++
programs in which the destructors are never invoked manually but do run.
This is not possible in Java.

You are still missing my point. In Java, all objects are on the heap. In
C++ you can put objects on the heap as well and when you do the
destructor is called manually using the delete statement. You may not do
it yourself (e.g. using an auto pointer) but it still exists in some
piece of code. You cannot write code for objects on the heap in C++ in
which the destructor for those objects run without there being a manual
invocation of delete somewhere in somebody's code. Therefore for heap
based objects there is little difference between C++ and Java.
In any case, I do not want to get into a word parsing you said/I said
match. I just want to make it clear that C++ destructors are not solely
invoked manually and have no comparable mechanism in Java. My apologies
if I misunderstood your post.

And it is not the lack of destructors you are talking about but the lack
of stack-based objects. For stack-based objects, yes the destructor is
invoked automatically when the object goes out of scope. All of the
cases where the destructor (really the delete operator) is not invoked
manually involve a stack based object of some sort. Either the object
itself is stack based or you use a stack based object to invoke the
delete on a heap based object (e.g. auto_ptr).

There is no automatic calling of destructors without stack based
objects. Therefore the issue is not destructors vs. dispose methods but
the lack of stack-based objects (or variables that hold objects).

Java has very good reasons for not having stack-based objects that far
outweigh the slight inconvenience of manually invoking a dispose method
on those objects that deal with non-memory resources.
There is a much bigger difference than you represent. In C++ you *must*
manually delete objects created via new or you get a memory leak.

And when I said that you have to manually delete objects above you told
me I was wrong! Java only has "objects created via new". And just like
in C++ you have to manually do something to dispose of it. In Java it is
only necessary for non-memory resources, but in C++ you have to do it
for every object.
Objects in Java do not *necessarily* have a method that must be called
to release resources.

Right. You only have to do it for non-memory resouces. But the point is
that just like C++ it is a manual process.
Right; the real point however is that creating local variables is
standard operating procedure in C++ while it is not possible in Java. So
in C++ developers have the option of using local variables and getting
the destructors invoked "for free". This option is not available in
Java, as you note below.

And it is this feature you are asking for, not destructors. Destructors
are meaningless in Java without this feature.
You'll have to be more clear here. I'm not even certain which language
you are referring to.

I was referring to C++. Consider this expanded version of the example:

class A
{
public:
virtual int foo() { return 5; }
};

class B : public A
{
public:
virtual int foo() { return 10; }
};

and this code to call it:

B b;
A a = b;
A *pa = &b;
cout << a.foo() << endl;
cout << pa.foo() << endl;

The fact that this prints:

5
10

is a point of confusion for many newbies.
I do not see how your conclusion follows. Destructors could be added to
Java with benefits. All that would really be necessary would be that
the JVM should guarantee that finalize() is called. Then
implementations of java.sql.Connection could close() themselves, etc.
There are many pitfalls there however and the designers of Java chose
not to include this benefit. To say it buys you nothing doesn't wash
however.

And when will they be called? Is it OK if they are never called until
the program shuts down? If you want it to be guaranteed to be some time
sooner than that you'll have to explain how the JVM can guarantee that.
 
D

Dale King

Paul said:
Perhaps not in the code you write. But most any useful program
has to get data from someplace and/or put it someplace else,
i.e., interact with stuff "out there" via things like files and
DB connections.

And I specifically mentioned files and DB connections. Still the
majority of objects are only dealing with memory resources and don't
need anything.
The use of try/finally is:

+ easily forgotten
+ easy to get wrong
+ tedious to write

You forgot to add:
+ pretty much the same as C++ when heap based objects are concerned.
+ the only real way to do it without objects in variables (stack-
based objects)
Java eliminates most memory-management concerns and errors, but
the price you pay is now having to worry about other kinds of
resources that Java gives you *zero* help with. It's funny how
that's never mentioned by the Java/Sun marketing literature.

And the only reason you don't in C++ is because of stack-based objects.
Stack-based objects cause dangling pointers, loss of polymorphism and
confusion to new programmers. But you don't read about that in the C++
marketing literature.
[finalize] is not guaranteed to ever occur, but some safety net is better
than no safety net.


I don't particulary care for Heisenberg programming.

Then please explain how you get anything else in this case.
 
P

Paul J. Lucas

Dale King said:
Paul J. Lucas wrote:

You forgot to add:
+ pretty much the same as C++ when heap based objects are concerned.

Not if you use auto_ptr said:
Stack-based objects cause dangling pointers

Only if you returns pointers or references to them.
loss of polymorphism

I've never found this to be a problem since the object is often
created in one place, but passed by reference to other places.
Those other places still have polymorphic use of the object
they're passed.
confusion to new programmers.

That personally doesn't concern me. I want a language that's
useful for *me*, not new programmers.
But you don't read about that in the C++ marketing literature.

C++ doesn't have nor has ever had "marketing" behind it just
like C didn't.
[finalize] is not guaranteed to ever occur, but some safety net is better
than no safety net.

I don't particulary care for Heisenberg programming.

Then please explain how you get anything else in this case.

Destructors when objects go out of scope or via auto_ptr<T>.

- Paul
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top