finalize() not guaranteed to be called -- ever

D

Dale King

Paul said:
Newbie confusion isn't my concern and reduction of it shouldn't
be the guiding principle of a programming language.

I think newbie confusion is really not strong enough a word. Frankly, I
think something like this may trip up old-timers as well. The
distinction between value semantics and reference semantics is probably
not very clear to many C++ programmers.
Why not just use stack-based objects?

Because it is unsafe and unsecure as others have explained.

Going back to where I started where I talked about 3 aspects of the end
of the lifecycle for an object:

1. Releasing of non-memory resources
2. Freeing of the object's memory
3. Elimination of the last reference to an object.

Stack-based objects allow 2 to occur before 3 which causes problems. The
real question is why is it assumed that 1 and 2 have to occur together?
That is the way C++ does it, but is that really the best way? I don't
think so. All we really care about is that 1 occurs before 2 and we
would like 1 to occur in a timely fashion. The using mechanism is one
way to do this.
 
D

Dale King

Paul said:
They could at least be *guaranteed* to be called before JVM

It can never actually be truly *guaranteed*. Not even C++ can guarantee it.
termination, something even finalizers aren't guaranteed to do
(and runFinalizersOnExit() is deprecated because it's broken --
well, *fix* it).

I don't think it is any more broken than C++ (actually I think it is
even less so). It is deprecated because of the fact that you can get
weird behavior and deadlocks due to multiple threads interacting with
the object at the same time. The same thing can happen in C++, but
because C++ really isn't a multithreaded language (any thread support is
an add on to the language) this problem is ignored. Even worse in C++
the object may be freed while another thread is accessing it. At least
in Java you are guaranteed that the object still exists.

So as I see it, runFinalizersOnExit is no worse than C++ and actually
slightly better.
 
D

Dale King

Paul said:
I want a language that allows more flexibility over safety,
i.e., a powerful tool for good programmers, not a language that
protects sloppy programmers from themselves.

BTW: lots of Java programs still crash for lots of reasons.

The issue is not so much protecting sloppy programmers from themselves,
but protecting users from malicious programmers.
And how many different ways can I explain that I want Java to
*have* objects created on the stack?

Or at least a special kind of reference that's equivalent to
auto_ptr<T>:

void foo() {
auto MyObject foo = new MyObject();
// ...
}

When foo goes out of scope, the referrent gets GC'd immediately
(unless it's still strongly reachable by some other means).

And I again ask why must it be garbage collected at that point? Isn't it
sufficient that the non-memory resources get freed (by calling a method
on the object) at that point? Why does the freeing of non-memory
resources and the freeing of memory have to occur at the same time?

And the answer is of course that they do not have to occur at the same
time, just in the right order. And there is a way to do that with the
try finally and as I mentioned C# has a cleaner syntactic sugar for
that. In C# your code would be:

void foo()
{
using( MyObject foo = new MyObject() )
{
// ...
}
}

It seems to me that you should petition Sun to add this syntactic sugar
(and I am not knocking syntactic sugar). There doesn't seem to currently
be an RFE for it. I'd vote for it if there were.

Don't bother even requesting to go back to the world of stack-based
objects because that will never happen (thank goodness).
 
D

Dale King

Chris said:
Dale King wrote:

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.
\>
There's nothing "stack-like" about allocating objects linearly. All[*] methods
of placing allocations will, if the space they are looking at happens to be
empty, place them in order. You might just as well claim that it was
"first-fit like"....

I don't know where your blind spot is here. It is *exactly* stack like.
To allocate space of size x subtract x from your stack pointer and the
new value of the stack pointer is the pointer to your allocated memory.
It is not "first-fit" like because allocation does not involve searching
through free lists for memory that fits.
It's the /deallocation/ that gives a stack its particular flavour, and using
the expression "stack like" when the deallocation does not follow FIFO
principles is just misleading.

But they specifically qualified it by saying allocation is stack-like.
They did not associate deallocation with a stack at all.
(I would, of course, have no objection to a sentence like "the implementation
uses a nursery space <insert description> which provides an approximation to
the benefits of stack-based allocation".)

Which would basically impart no knowledge whatsoever. I'm sure there is
probably a more precise term for this type of allocation, but it would
not be as well known as a stack.
 
R

Raymond DeCampo

Dale said:
I think the real solution is to adopt a feature similar to the using
statement from C#. This is really only syntactic sugar for the
try-finally, but it is a much cleaner syntax particularly when you need
to use several resources. See




And how is that in any way different from runFinalizersOnExit()?

I've addressed that in other posts. The real difference is that since
Java doesn't have an fully endorsed destructor mechanism that everyone
can count on be called, nobody implements halfway finalize() solution.
Specifically in libraries and JRE provided code.

Ray
 
C

Chris Smith

Paul J. Lucas said:
I still don't see what that has to do with having stack-based
objects, destructors, or reference-counted objects.

It has to do with what you wrote several messages ago:

[1] Java doesn't guarantee your safety in many other areas. For
example, try writing an equals() without a hashCode() (or vice
versa) and see what kind of trouble you get into. So why should
Java be so fascist about memory safety? It's seems heavily
lop-sided as if memory problems were the obly problems with
programs.

As for the general thread, I could guess the relevance. Having stack-
based objects definitely opens the door to all sorts of mistakes that a
programmer can make that lead to undefined behavior. Since these would
negate the Java security model, they can't be allowed. A language with
stack-based objects that avoids those dangers would have to create a
very limited set of possible operations.
Have a twin class for Object: CountedObject.

Would you then provide a mirror of the Collections API that works with
CountedObject instead of Object? CountedList? CountedLinkedList?
CountedArrayList? etc. How about all the Swing classes that use Object
as a model data type? Would you introduce JCountedTree? JCountedTable?
JCountedList?

Take a look at the API documentation for java.lang.Object, and click the
link on the top of the page that says "Use". Every single one of those
classes or methods would need a mirror that uses CountedObject instead
of Object.

IMO, it's definitely not worth throwing away the single-rooted class
hierarchy in order to prevent deferred collection in a few cleanup
cases.

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

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

Chris Smith

Chris Uppal said:
I believe that reference counting (in a sufficiently sophisticated
implementation) is feasible and may even bring overall performance benefits as
heap sizes grow and grow.

(Indeed the programming language I use has a bit of ref-counting mixed into its
memory management as a performance booster.)

Which language are you referring to here?
What ref-counting cannot bring you is a safe, usable, implementation of the
semantics that Paul is asking for -- the problem of cycles is not solvable in a
way that simultaneously compatible with less-than-Godlike programmers and
"normal" Java references-to-objects.

www.cs.kent.ac.uk/pubs/1992/122/content.ps.gz is written by Richard
Jones and Rafael Lins. I trust them far more than most anyone else
regarding whether the cycle problem is solvable. It can, but there are
performance problems.

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

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

Dimitri Maziuk

Paul J. Lucas sez:
I want a language that allows more flexibility over safety,
i.e., a powerful tool for good programmers, not a language that
protects sloppy programmers from themselves.

And herein lies your problem. Salary difference between a good programmer
and a self-taught-in-21-days code monkey is enough to buy several faster
CPUs a week to compensate for inefficiency. Not to metion that the smart
guys do forget to delete things every once in a while, or delete things
earlier than they should, and that leads to hours of debugging -- again,
at the cost of a[t least one] faster computer.

It's not just Java -- look at, say, SOAP, for one example. Anyone with
half a clue knows that 99% of what it's used for can be accomplished 99%
more efficiently by designing your own data exchange protocol. Yet that
requires someone who can design a protocol and code a decent server.

So you may want whatever you want for as long as you want, it's what
pointy-haired managers want that counts.

HTH
Dima
 
P

Paul J. Lucas

Thomas Hawtin said:
Paul J. Lucas wrote:

You are familiar with C++?
Very.

When the destructor of a resource is invoked and there is an error
closing that resource, what happens?

It depends. If the error propagates by a simple return code,
then what happens is whatever the author of the destructor says
happens. The author can ignore it, log it, set a flag
somplace, or die... just don't throw an exception.

Your point?

- Paul
 
P

Paul J. Lucas

Chris Smith said:
Would you then provide a mirror of the Collections API that works with
CountedObject instead of Object? CountedList? CountedLinkedList?
CountedArrayList? etc. How about all the Swing classes that use Object
as a model data type? Would you introduce JCountedTree? JCountedTable?
JCountedList?

If Java had true templates like C++ from the beginning, this
would be a no-brainer.

- Paul
 
P

Paul J. Lucas

Dale King said:
Paul J. Lucas wrote:

And I again ask why must it be garbage collected at that point? Isn't it
sufficient that the non-memory resources get freed (by calling a method
on the object) at that point?

Fine: guarantee that as soon as foo goes out of scope, its
finalizer will be called. Whether or not the memory is
reclaimed is irrelevant.
And there is a way to do that with the try finally and as I mentioned C# has
a cleaner syntactic sugar for that.

Except we're talking about Java.

- Paul
 
C

Chris Smith

Paul J. Lucas said:
Fine: guarantee that as soon as foo goes out of scope, its
finalizer will be called. Whether or not the memory is
reclaimed is irrelevant.

That's a more reasonable feature request, then, from a technical
standpoint. I can definitely see a good reason to include it. I'd like
to see -- for example -- a keyword "auto", such that:

{
auto MyObject obj = <expression>;
...
}

is equivalent to:

{
final MyObject obj = <expression>;
try
{
...
}
finally
{
obj.close();
}
}

Using finalize() for this just feels wrong... but perhaps because using
finalize() at ALL just feels wrong in Java.

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

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

Thomas Hawtin

Paul said:
It depends. If the error propagates by a simple return code,
then what happens is whatever the author of the destructor says
happens. The author can ignore it, log it, set a flag
somplace, or die... just don't throw an exception.

So no exceptions from errors discovered in the destructor, then.
Your point?

The destructor of ostream will "remain silent" even if there is an error
closing the stream.

Tom Hawtin
 
T

Tim Tyler

Paul J. Lucas said:
They could at least be *guaranteed* to be called before JVM
termination, something even finalizers aren't guaranteed to do
(and runFinalizersOnExit() is deprecated because it's broken --
well, *fix* it).

Sun claim it it *inherently* broken:

``runFinalizersOnExit(boolean value)
Deprecated. This method is inherently unsafe. It may result in
finalizers being called on live objects while other threads are
concurrently manipulating those objects, resulting in erratic
behavior or deadlock.''

- http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Runtime.html
 
T

Tim Tyler

Paul J. Lucas said:
Newbie confusion isn't my concern and reduction of it shouldn't
be the guiding principle of a programming language.

It's important. Programming languages should be easy to learn -
otherwise nobody will bother to learn them - and without a steady
influx of newbies, programming languages die off.

IMO, Java doesn't score very well on this front any more. It's a large
rambling beast, with a language spec that is now reaching biblical
proportions.
 
T

Tim Tyler

Paul J. Lucas said:
Fine. Rather than have a special kind of reference, have a
special kind of class:

public counted class MyClass {
// ...
}

Then the JVM knows exactly which classes are reference counted.
Any class derived from a counted class is also counted.

Reference counting is not used because it doesn't work very well.

Circular references cause objects to never be disposed of.

Additionally, there are memory costs and maintenance costs associated
with the references.

If the proposed benefit is having more deterministic destruction of
resources, that has to be weighed against the fact that reference
counting doesn't actually work very well.
 
T

Tim Tyler

Chris Uppal said:
Dale King wrote:

I believe that reference counting (in a sufficiently sophisticated
implementation) is feasible and may even bring overall performance
benefits as heap sizes grow and grow.

``Reference counting is nearly always very much slower than other garbage
collection techniques, because of the need to update reference counts
whenever a reference is changed, rather than only following references
during garbage collection. Reference counting also requires some space
in each object.''

- http://en.wikipedia.org/wiki/Garbage_collection_(computer_science)

IMO, the biggest problem with reference counting is not performance -
it's that it doesn't deal with circular references - resulting in
accumulating memory leaks. If you use it, you *still* have to do
something like mark-and-sweep, to clean up after it.
 

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

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top