Fog Creek Software
Discussion Board




RAII vs. Java

Many moons ago, Joel wrote:

"Programmers are much more productive in languages that do the memory management for them."

http://www.joelonsoftware.com/articles/fog0000000051.html

And he goes on to talk about C++ being useful if it's faster.

But in my experience, Java is a pain because there is no destructor.  I'd rather have an unmanaged language with a destructor.  Say you have a database connection that you have to close.  How do you avoid writing this 10,000 times:

try{
...
}
finally
{
    if(db_conn != null)
    {
        db_conn.close();
    }
}

RAII seems like a pretty good thing.  From my experience, I hardly ever need to spend much time on memory management in C++.

ECH
Monday, July 12, 2004

C# has a "using" statement that will call the "Dispose" method of the instance's IDispose interface when the instance goes out of scope; it's similar to a C++ destructor, for instances of classes that implement IDispose.

Christopher Wells
Monday, July 12, 2004

Java surely has an idiom or a language construct for what you want to do. How could it be used as an enterprise tool by the likes of IBM if it didn't?

I don't know the answer, but I feel sure that if I looked for it it would not be a fruitless search.

Ian
Monday, July 12, 2004

I'm not sure I understand Ian's comment, but ECH is correct.  The only problem with RAII is that the return value of the close function is lost.  Sometimes the close function provides important information, and its value must be checked. 

christopher (baus.net)
Monday, July 12, 2004

if you're writing that 10,000 times, then your problem is code organization, not a problem with Java.

I work with database applications pretty much every day (what developer doesn't?) and I've never had to do what you describe in Java.

(or perl either, for that matter, and while Perl HAS destructors, I never use them)

muppet from forums.madebymonkeys.net
Monday, July 12, 2004

I don't think it does. I'm not sure you can have garbage collection and deterministic finalization, if only because objects won't necessarily ever get collected. So the way you manage your non-memory resources in Java is... yes... by hand.

Tom
Monday, July 12, 2004

Even in C#, which has finalizers, you should *always* release your connection as soon as you're done with it.

It may be convenient to leave it to the destructor, but you never know when your object is going to get GC'd, so you may be tying up extra resources unnecessarily for great lengths of time (which could cause a performance hit in high-volume situations).

Maybe Java left out destructors simply to stop people from doing things like this ;-)

Joe
Monday, July 12, 2004

"How could it be used as an enterprise tool by the likes of IBM if it didn't?"

How could C be used by the likes of IBM if it didn't? In Java you do have to do this kind of stuff by hand. C# is a little better, but not much. In C++ you barely have to think about such things.

As for mixing garbage collection and deterministic destruction, managed C++ in Visual Studio 2005 can do that just fine. To quote Microsoft:

"What happens when my instance on the stack goes out of scope? How is it cleaned up? Many C# developers have complained about the C# language's lack of deterministic cleanup. The C# language provides the using keyword to make it easy to dispose of an IDisposable object, but this requires extra code and is clunky compared to the destructor pattern familiar to C++ developers. In C#, safe cleanup is off by default and requires explicit coding.

...

Visual C++ 2005 now provides the ability to have destructors and/or finalizers on any type, regardless of whether it is managed or native. In the case where the type is managed, the compiler maps the destructor to the IDisposable::Dispose method. This means that you can write the same method in C++ using the fourth snippet in Figure 3, where reader's destructor/Dispose method will automatically be called just as if you were using the "using" statement in C#. When a type is created on the stack, its destructor is invoked when it goes out of scope."

(From http://msdn.microsoft.com/msdnmag/issues/04/05/visualc2005/default.aspx )

sid6581
Monday, July 12, 2004

As for the times you want to check the return value of the close function, there's always the option of simply calling a Close() method explicitly. You can do it both ways.

sid6581
Monday, July 12, 2004

Yes, you have to do it by hand, every time.  But as was mentioned above, you probably have this hidden behind a data access layer, so you don't code it all over the place.  You do code it much more than if you wrote it in a language with destructors, though.

Brian
Monday, July 12, 2004

"Data access layer". Sounds like you're working on business software and you're only considering database stuff. In my work I have hundreds of different resources I'm managing, all over the code, and destructors greatly simplify my work and my code. Similar code in Java would be much longer.

It's interesting that people consider garbage collection to be such a godsend, when it so complicates other resource management. Especially when C++ never had any problems with memory management in the first place, if only you're smart enough to realize that it's not C, and shouldn't be programmed like it is C.

sid6581
Monday, July 12, 2004

I don't find resource management complicated.  You should realize that Java is not C++, and not attempt to program it as if it were.  ;)

muppet from forums.madebymonkeys.net
Monday, July 12, 2004

I don't know what kind of code you write, but resource management and gracefully handling errors is in my experience (after having programmed for over 15 years) the hardest thing to get right. Thankfully, C++ makes it extremely easy. I barely have to think about it anymore.

I have had several professional jobs writing Java code, and I have to admit I didn't like it one bit.

sid6581
Monday, July 12, 2004

so that's your preference.  Why pontificate on why java is a poor language when clearly, there are hundreds (thousands) of people who disagree with you?

muppet from forums.madebymonkeys.net
Monday, July 12, 2004

"if you're writing that 10,000 times, then your problem is code organization, not a problem with Java."

I hope you're right.  And the code is certainly poorly organized in general.  But I'm not sure the way to fix the problem at hand, muppet - can you point me in the right direction?  Thanks!
--------------------------
"managed C++ in Visual Studio 2005 can do that just fine" - Herb Sutter is my hero!

ECH
Monday, July 12, 2004

Because this is the Joel on Software forum, and we are discussing one of Joel's claims that some of us disagree with. I kinda thought that's what this forum was mostly about.

sid6581
Monday, July 12, 2004

And the main reason I dislike Java is because it doesn't have deterministic destruction. Sorry I didn't make that clear. (There are plenty of other reasons to hate Java, but I'll leave that for another day.)

sid6581
Monday, July 12, 2004

"Herb Sutter is my hero!"

Yep, very good of MS to bring him on board. And now we have proof that it's possible to mix GC and deterministic destruction, so I guess their excuses for not including them in C# don't really hold water. (I would love to find their excuses again -- I know this was discussed and MS replied on that subject.)

sid6581
Monday, July 12, 2004

My comment above was written out of a considerable lack of knowledge (that is, ignorance), but I still feel that handling database connections must be a common enough requirement in Java code.

Is there not some standard way of localizing the references to unmanaged resources and freeing them in a deterministic manner? Like perhaps using a standard interface package that looks after the nitty gritty details for you?

Ian
Monday, July 12, 2004

No, there's no way to fix this problem without language support for it. C# has a little bit of support as indicated in this article:

http://www.jaggersoft.com/pubs/ExceptionHandlingInCSharp.htm

In C++ you could easily write the ideal version. In C# it's a little bit better, but it doesn't scale well if you need to use multiple resources in the same function. In C# you also have to explicitly write a Dispose() member function to dispose of member resources, whereas in C++ you can ignore that since it's done automatically. In Java it's just a mess, as you can see from the article.

sid6581
Monday, July 12, 2004

Ian - of course there is.  But some programmers have gotten extraordinarily lazy and want all technologies to work similiarly (as little innovation as possible) so that they don't have to try so hard to learn new things.

Yes, you can wrap your connections up nicely and manage them intelligently in a database class with a small amount of effort.

muppet from forums.madebymonkeys.net
Monday, July 12, 2004

It's only a mess if you are so narrow minded that you cannot conceive of a language that doesn't behave like (insert your favorite language here)

expand your minds a bit, gentlemen.

muppet from forums.madebymonkeys.net
Monday, July 12, 2004

Expand our minds? I have experience with over a dozen different languages, many of which I have used professionally. I think I have a good basis for comparison.

That others disagree is fine, I'm only stating my opinion, and I didn't pull it out of my ass. There's a reason my favorite language is my favorite language: My experiences with the different languages over the last decade and a half.

For the sake of brevity I'm not prefixing every sentence with "my opinion is:", but read it that way. I'm not stating that my opinions are absolute fact, so please don't reply as if I do.

sid6581
Monday, July 12, 2004

+++No, there's no way to fix this problem without language support for it.+++

Either you're implying here that Java has no support for resource management (which is ludicrous), or else this statement is just flat out meaningless (water is wet).

Opinions, fine.  Flat out lies, I'm going to call you on.

muppet from forums.madebymonkeys.net
Monday, July 12, 2004

While it's true that you can abstract away some of it, it's not possible to make it all go away for the general case. Unless you call everything beyond your main() an abstraction, and totally ignore the fact that you'll have to write a lot of the abstractions yourself.

I'm not saying you can't alleviate the problem, but you can't make it go away in Java. (Unless all you ever do is call third party libraries that don't have resources you need to dispose of.)

If you still think I'm wrong, please clarify your position.

sid6581
Monday, July 12, 2004

no, you're right, you'd have to write some small database abstractions.

OR, in other languages, you'd have to write some destructors.

what the holy hell is the difference?  If you contend that writing small abstractions is harder than writing destructors, then you're not doing it right.

muppet from forums.madebymonkeys.net
Monday, July 12, 2004

The difference is that in C++ you could stop the abstraction at the object level, and as a user of the object you don't have to worry about any cleaning up for that object. The object cleans up after itself. This is true for member objects as well, so a lot of the time you don't even have to bother writing a destructor.

In Java, if you stop at the object level and instantiate a class, you are responsible for cleaning up for that object everywhere you use it, so you have to abstract at a higher level. Abstraction and refactoring is good, of course, but most of the abstractions written to hide this manual labor in a typical application is code you have to write yourself, and you'll have to deal with the resource management over and over and over every time you use a resource. In C++ you only have to worry about it once, when you write the resource abstraction itself.

sid6581
Monday, July 12, 2004

> what the holy hell is the difference?

The difference is that in C++, assuming that the DBConnection class is coded correctly with a destructor that closes it if it's open, then I can write client code like:

void foo()
{
  DBConnection connection;
  connection.open();
  ... use connection ...
}

I dn't need to write code to close it; and, especially, I don't need to handle the exception if using the connection thows an exception.

Whereas the equivalent Java (forgive me, I don't know Java) code must presumably be like this:

void foo()
{
  DBConnection connection = new DBConnection();
  connection.open();
  try
  {
    ... use connection ...
  }
  finally
  {
    connection.close();
  }
}


> Yes, you can wrap your connections up nicely and manage them intelligently in a database class with a small amount of effort.

Perhaps you're suggesting a DB connection pool. But in Java, I (a client of this pool) would still need to hand-write statements to tell the pools exactly when I have finished with any given connection (so that the connection instance can be closed or reused).

Christopher Wells
Monday, July 12, 2004

Err... I use one database object per connection (usually ONE).  When I'm no longer using the object, I call ->disconnect() on it, and then let it fall to the GC.  Where am I dealing with freeing the resource "again and again" ?

I've yet to encounter a scenario where the above hasn't worked perfectly well.  Java isn't harder to use than C++, you just don't properly understand how to use it, apparently.

You're right, you can't deal with things the way you do in C++, so you may have to structure your code differently.  However, this does NOT necessarily (or even usually) mean more code.

Hence my "expand your mind a bit" comment, earlier.

muppet from forums.madebymonkeys.net
Monday, July 12, 2004

Christopher:  so you have to write one line of code to close the connection.  So what?  I'm still missing the problem here.  If your contention is that in X locations in the code, you need two lines instead of one to deal with a connection, then I'm having trouble drumming up sympathy for you or even recognizing where the problem is.

muppet from forums.madebymonkeys.net
Monday, July 12, 2004

> so you have to write one line of code to close the connection.  So what?

So someone might forget. Now imagine that I'm the C++ author of the DBConnection class: I may for example code its destructor properly, and (by declaring its "operator new" as private) try to forbid its being created on the heap; by doing this I encourage clients (who use the class) to create it only on the stack and, because it's deleted automatically as soon as it goes out of scope, I've removed the need the close it explicitly and reduced the possibilty that one of the clients who use the class is able to use it improperly.

I think the OP is saying that he has 10,000 places in his code where wants short-lived objects that release their resources automatically when they go out of scope.

I don't know what his situation is exactly ...

In the past I've used this C++ idiom for critical sections (release the crtitical section when the critical section lock instance goes out of scope); and I've used it for adding microtimers to a subroutine (stop timing when/wherever the subroutine exits); and I don't remember off-hand what else, because it's so common.

Christopher Wells
Monday, July 12, 2004

"so you have to write one line of code to close the connection.  So what?  I'm still missing the problem here"

so you have to write one line of code to free the memory.  So what?  I'm still missing the problem here.

(Actually I'm not missing any problem, I'm being sarcastic.)

Well, muppet? You've just "successfully" argued that a garbage collector is a complete waste of time - so why do we need them? After all, calling 'allocate' and 'free' methods works just fine, according to your interesting logic.

Why don't you expand your mind, and ponder the fact that some people not only like the garbage collector, but think that automatic resource management is a really useful thing in all sorts of places?

The amusing thing is how casually you can say "and then let it fall to the GC" yet not so long ago people just like you were explaining that a little care and attention would eliminate memory leaks and that there was no problem to solve.

nothing every changes, does it?
Monday, July 12, 2004

People like me?  No.  I've always though that the manual tedium that is C/C++ was a waste of time.

As for how I've argued that the garbage collector is a waste of time, I guess I miss your point.  99% of the time, I'm worried about freeing memory.  The GC does that for me.  The other fraction, I'm worried about non-memory resources.  Those I do manually.

I'd rather do 1% of my resource management manually than 99%.

In any case, I don't see where one language is better or worse than the other.  It all seems to balance out.  All things being equal, it comes down to preference and prejudice.  A Java vs C++ debate comes down to a bunch of folks trying to justify their particular prejudice.  What's the point?

muppet from forums.madebymonkeys.net
Monday, July 12, 2004

As I mentioned, C# compromises: rely on the GC to recover memory, and explicitly implement and invoke IDispose if the class manages non-memory resources.

> In any case, I don't see where one language is better or worse than the other.

One's better here for this reason and the other is better there for that reason.

Christopher Wells
Monday, July 12, 2004

Muppet, your programs only have one resource, one database connection that you only use in one place?

Good for you, but the rest of us are writing programs that are a little more complex than that. I'm sorry you can't see beyond your own little world and see the benefit of being able to write less code and have more guarantees about correctness and robustness. Those things must not be high on your list.

sid6581
Monday, July 12, 2004

no, idgit, I didn't say they had only one resource.  I said typically I only need one database connection.  Sometimes I need *gasp* three.  One per database.  What else do you need?

How hard is it to call cleanup methods on 3 objects?  Apparently that's pretty tough in YOUR little world.

muppet from forums.madebymonkeys.net
Monday, July 12, 2004

Wow -- THREE resources you need to clean up. You're only revealing that your programs are incredibly simple. For comparison purposes, in my application I typically have about 20 files open at a time, several hundred threads, hundreds of COM objects, hundreds of critical sections, multiple sockets, dozens of windows, RPC connections, etc.

That's a little more complex to manage than three database connections.

sid6581
Tuesday, July 13, 2004

several hundred threads, hmm.. Do all hundred have unique code?  Wow, you really DO suck at writing code, if that's the case.  Same for your files, etc.

Yep, you're right, you may need many many resources open at once.  If you're coding a unique, specialized class for each of them to the point where you have to worry about cleaning up after each one individually, then you're a poor developer.  At least, a poor Java developer.

Stick to C++ then, I guess, since it allows you to make a huge mess by cleaning up after your sloppy coding practices for you.

muppet from forums.madebymonkeys.net
Tuesday, July 13, 2004

Uh. No. Threads are also resources, and subject to cleanup needs. They have an owner, and the point is that this owner doesn't have to worry about cleaning up after them.

And I don't know how in the world you got from what I wrote to this: "If you're coding a unique, specialized class for each of them to the point where you have to worry about cleaning up after each one individually, then you're a poor developer."

Here I am saying that you only have to write cleanup code once, and that you then no longer have to worry about cleaning up in many different places, and your reply is the above? Sheesh.

Tell me, how much experience do you have with C++ anyway?

sid6581
Tuesday, July 13, 2004

You're arguing that because you have multiple threads, you have to do cleanup multiple places.  I'm arguing that if you write your threads properly, your cleanup in Java amounts to ONE LINE.

If that's the cost of garbage collected memory management, I'll take it.

muppet from forums.madebymonkeys.net
Tuesday, July 13, 2004

No, I have several different types of threads that I use in several different places. The same type of thread is also used in different places. They are resources that are used by various consumers. When you use various resources in thousands of different places in your code, your Java solution will have to explicitly clean up those resources in all the thousands of different places. That's added code and complexity, and probability dictates that you will get more bugs because of that.

To clean up _properly_ in Java you'll need multiple lines of code (not just one line, especially if you need to allocate several resources in one function) EVERYWHERE you use an object directly. The article I posted a link to shows you how to write exception safe resource cleanup in Java.

sid6581
Tuesday, July 13, 2004

If minimizing lines of code is important, why aren't you using a scripting language like Python instead of Java or C++?

As someone mentioned earlier, typical code allocates memory hundreds of times more often than it deals with any other resource. Automating the stuff you do over and over is a massive win, the biggest advantage I saw when switching from C to Java.

Also, the less minutae you have to worry about when programming, the better. In C, I put tons of effort into making sure I freed all memory allocations exactly once. Rational Purify, a very sophisticated tool, exists primarily to catch the inevitable screw-ups arising from manual memory management. Not having destructors is a small price to pay for automatic memory management.

Julian
Tuesday, July 13, 2004

sid6581,  you clearly don't like Java.  Good for you.

Some of us do,  good for us.

It's been *years* since I've written code to directly open Databases, files,  sockets etc.  There are plenty of Open Source libraries to make this sort of thing effortless (check out JdbcTemplate from the Spring Framework for an example.

I'll gladly use a framework to handle all this stuff for me, I'll write:

f(g(new x()));

and you can write

x the_x = new x();
b the_b = g(the_x);
f(the_b);
delete the_b; // or does the library?
delete the_x; // or does the library?


Now you go off and write your C++, I'll write my Java.

Koz
Tuesday, July 13, 2004

ScopeGuard, kids, ScopeGuard.

Muppet what you are missing is that you can have multiple return paths from a C++ function an not worry about resource management.  In C this is done by using goto.  A lot of people claim this is a good use of goto:

foo()
{
  int handle = CreateResource();
  //
  // do stuff
  if(error){
    goto cleanup;
  }
  //
  // do more stuff
  //
cleanup:
  DestroyResource(handle);
}

RAII is IMHO much cleaner and less error prone. 

christopher (baus.net)
Tuesday, July 13, 2004

sid6581, for what it is worth, I completely agree with you.  Your code is clean examples, and from my daily Java and C++ I see your point and feel your pain.

Something for Java 1.6?

i like i
Tuesday, July 13, 2004

Ah, broaden the scope Chris!

A good use of goto:

bool transaction() {
  // commit
  if(!step1()) goto rollback1;
  if(!step2()) goto rollback2;
  if(!step3()) goto rollback3;
  // success
  return true;
  // rollback
  rollback3: undostep2();
  rollback2: undostep1();
  rollback1: return false;
}

Sorry, couldn't resist.

i like i
Tuesday, July 13, 2004

There are garbage collectors for C++ too.  Though they really ought to be part of the standard library.

Kalani
Tuesday, July 13, 2004

This argument is quite amusing.  I am a Java guy and I must admit that sometimes I wish that Java could guarantee a method is run on object destruction.  It can't though and it rarely turns out to be as big a deal as say, having to destroy one's objects explicitly.

For applications that are as complex as sid mentions, I would consider using a J2EE application server. EJBs do have the equivalent of a destructor but I still wouldn't use them to close database connections.  Standard practice is the app server maintains a connection pool for you and you call close() in the finally clause of any method that uses the connection (waiting for the object to be destroyed is bad practice anyway).  THis actually doesn't "close" the connection but rather returns it to the pool.  THe advantage?  Next time you open a connection it is nice and fast because it is already open and you are just getting it from the pool.

name withheld out of cowardice
Tuesday, July 13, 2004

The huge difference between Java and C++ programmers on this issue isn't surprising.  You almost never see finalizers written in Java and they hardly do anything interesting because of the non-deterministic destruction of Java objects.

In C++ however, destructors are used all the time and in many more situations.  The examples given above (Database connections, files, etc) are quite bland.  There are non-obvious stuff like UI elements: Window object goes out of scope so the destructor closes the window on-screen and frees the OS resources.

The biggest advantage of deterministic destruction comes with exceptions.  In C++, there is no "finally" clause -- exception handling is a lot less cluttered.  Try blocks are much less common in C++ (and remember, the value in exceptions is in NOT handling them).

I'm extremely pro-GC but I'd also like to see deterministic destruction.  Java developers really don't know what they are missing!

Almost Anonymous
Tuesday, July 13, 2004

Julian, Python isn't a good choice for the kind of high performance client and server applications I am writing. I write video applications, I need the performance. But that's not really the point. The point is that deterministic destruction is a good thing, regardless of whatever pros or cons the various languages may have. If Java had deterministic destruction it would still retain the other benefits it has as a language, but would have an additional benefit. There are things Java to better, and there are other things C++ does better. This is just one point where C++ is much better.

Also, why do you bring C into this? C++ isn't C. In C++ I don't worry about memory allocations either, because it's just a resource like any other. Garbage collection solves a problem I don't have, so I don't see how it is a massive win over C++. Over C, sure, but not C++.

We're arguing the same thing: The less you have to worry about these details, the better. In C you have to worry a lot, in Java you have to worry less, and in C++ you don't have to worry at all.

sid6581
Tuesday, July 13, 2004

Btw, I'm not saying garbage collection is useless. It has its merits, but for someone coming from C++ who already knows to avoid manual memory management, it doesn't solve a problem I have.

sid6581
Tuesday, July 13, 2004

Sid,

You're still doing manual memory management -- it's just not as manual as doing it in C.  The biggest issue with C++ memory management is "ownership".  You always have to be clear who owns what object and who cleans it up.  In Java, you don't have that worry.  It's essentially one less thing to specify between in an interface. 

Example: If I give you an object, do you delete it or must you call me to delete it?  Or is it a pointer to a static buffer that doesn't get deleted?  If the the object is in two (or more) containers, when does the object get cleaned up?  It really goes on and on. 

Almost Anonymous
Tuesday, July 13, 2004

The big advantage with GC or RAII is that in GC memory collection is the default behaviour.

If a newbie grabs lots of memory for themselves and doesn't give it back the system cleans it all up for them.

RAII is far more efficient, but requires good behaviour on the part of the programmer.  For RAII to work you have to obey all the rules.  You have to acquire in the constructor and release in the destructor.  You have to ensure that all code after the acquisition within the constructor is exception safe.  If aquiring a resource outside the constructor is unavoidable, you have to release it yourself or use an autopointer.

If you fail to follow every last one of these rules, your resource allocation will fail.

To summarise:
  * With RAII is damaging.
  * With GC the default behaviour is harmless.

RAII is, however, so much more efficient.  Isn't there be a language that enforces the conditions necssary for With RAII at compile time?

Ged Byrne
Tuesday, July 13, 2004

As you can tell from the mangling of my previous thread, anything that relies on me doing things right is to be avoided.

Ged Byrne
Tuesday, July 13, 2004

AA: True, but at least the way I code I rarely give up ownership of heap allocated objects to others. When I do, I typically take a std::auto_ptr as an argument where I want to take ownership of the pointer that is passed in. In practice there has never been a confusion about this for me in my own code or interfacing with other people's code, but you're right, you do have to be clear about these things.

Ged: For newbies GC is easier for memory allocation, but I think it's easier with RAII for other resources. The problem, I think, is that many are not aware of RAII, or are not aware of how much it can simplify code. However, for RAII to work you don't really have to acquire in the constructor. Most people take RAII to mean cleaning up in the destructor and consider RAII to be a misnomer, and skip the constructor part of it. Resource allocation is in common practice typically done in a separate method, not in the constructor. It doesn't matter how you do it, really. All you need to do is clean up in the destructor, and most of the case that's pretty trivial.

I could be wrong, but I do think it's easier for newbies to get RAII right than the manual resource management you have to do in Java. Once they realize what RAII is, that is. And keep in mind I'm not talking about just memory here. In C++ there's already solutions in place for automatic memory management, such as std::auto_ptr and the containers. In my current project (which is pretty large) I think I have maybe two or three explicit deletes across all the applications. The only reason they are there are because I'm passing raw pointers through window messages, so it's not a fault of C++. If I really wanted to I could get rid of those, too.

sid6581
Tuesday, July 13, 2004

I agree that it's easier for newbies to get RAII, the problem is the way that C++ implements it.

RAII is not the default behaviour in C++, you have to work in order to get it.  If you do something wrong, then you lose all the benefits.  This is why I stay away from C++, I'm a guy who gets things wrong a lot.

Lacking RAII, my favourite method is the Ruby approach:

File.open(fname) do |file|
    #Do what has to be done with the file
end

Much cleaner than all those try...finallys.  The approach in Java, using anonymous inner classes, is wordier but still useful.

Ged Byrne
Tuesday, July 13, 2004

In response to A.A.'s post, it is a complete misnomer that Java relieves a programmer of their duty to manage memory. It is always a programmer's concern to know how an application is managing memory. Not doing so would be irresponsible.

A java application can just as easily leak memory as one written in C++ or any other language. Consider when the last reference to an object is set to NULL in a Java application. This action is generally assumed to cause the memory to be recovered by the G.C.. If another module still maintains and uses that pointer then this is a rather hard to detect software design flaw, but still constitutes a memory leak in that the memory is not recovered when it is expected to.

--
http://www.heron-language.com -> no G.C. and proud of it.

Christopher Diggins
Tuesday, July 13, 2004

"A java application can just as easily leak memory as one written in C++ or any other language."

How?

"Consider when the last reference to an object is set to NULL in a Java application. This action is generally assumed to cause the memory to be recovered by the G.C."

Following you here...

"If another module still maintains and uses that pointer then this is a rather hard to detect software design flaw"

Err, didn't you just say this was the last reference to an object?  So what's the module that maintains this pointer? 

I've read you comment and number of times and I just plain don't get it!

Almost Anonymous
Tuesday, July 13, 2004

Sorry, I was not clear. I should have said "when [what is believed to be] the last pointer ..."

I am trying to make the point that memory management is always a concern of a programmer, and that it can be mismanaged irregardless of the existance of a G.C. in a language. 

Christopher Diggins
Tuesday, July 13, 2004

"when [what is believed to be] the last pointer..."

Err ok.  Well the garbage collector knows what objects are currently being pointed to from other places.  So no matter what, it knows exactly when the last pointer to an object is gone.  Only at the point, does it clean up. 

There is no way, in pure Java code, to leak memory in Java.  Nor is it possible to have a reference to an object that has been cleaned up the collector (again, we're talking about pure Java code).

I think ultimately I'm missing the point.  But I've been using garbage collected languages since I was 8 years old (Commodore 64 basic!) and I don't worry about memory management.  There's only example I can think of and that's handling circular references in Visual Basic (because it's reference counted) -- which is not a problem for Java or .NET.

Almost Anonymous
Tuesday, July 13, 2004

"I am trying to make the point that memory management is always a concern of a programmer, and that it can be mismanaged irregardless of the existance of a G.C. in a language. "

Amusingly, Microsoft seems to agree - they have resources describing different memory allocation strategies in .NET langauges and describing their impact on performance. Sure, it's not memory leaks but it's still an issue and it's easy to overlook if you're one of the shiny new developers learning that you can just allocate memory when you need it and not care about it when you're done.

garbage collection - the ultimate silver bullet!
Tuesday, July 13, 2004

Memory management in Java (and in GC systems) is
simpler, but not non-existent. It is always possible that
you hold last pointer to huge structure of objects
unneedlessly, thus still effectively "leaking" memory. And
you should not underestimate such possibility if you deal
with really complex structures.

On the other hand, RAII imposes stack-like discipline for
memory (and resource) allocation, which is used most
widely - we are people and think best in hierarchical
manner, that is with a stack inside our brain - but not
universally.

My favorite language, Python, has ref-counted GC which
apparently provides you with predictable resource
deallocation, but do not handle well circular references.
But, it happens that this mentioned hierarchical thought
systems leads to very rare occurences of these circular
references in practice. So rare, that Python people did not
even bother with considering "fair" GC.

So I recently got used to idiom:
def some_func(file_name):
  for line in file(file_name):
    do something
and do not care about closing the unnamed
file reference - it will be closed right at the
return point where the scope is leaved.

Victor Joukov
Tuesday, July 13, 2004

I think Victor states the case better than myself.

I wanted to add to the discussion, because I think it is relevant and interesting. Reference counting has gotten  a bad rep. The C++ Boost smart pointer library ( http://www.boost.org/libs/smart_ptr/smart_ptr.htm )  deals with the circular reference problem by not including "weak" pointers in the reference count. I used a similar model in the Heron language as well because it is simple, efficient and effective. Heron heron has two classes of object reference (strong and weak) where strong references are reference counted among themselves. ( http://www.heron-language.com/basics.html#refs )

Christopher Diggins
Tuesday, July 13, 2004

Reference counting is all good until you have multithreading.  The locking for maintaining the count will kill your performance.  Otherwise, I fully agree.

Almost Anonymous
Wednesday, July 14, 2004

"RAII is far more efficient"

That is completely implementation dependent.

However, an optimal GC algorithm will usually beat manual memory management in terms of speed. Of course, manual memory management will typically have the advantage in terms of space (provided you don't have memory leaks!)

The other advantage of GC is locality of reference - if you use a compacting GC, then all your objects will be close together in memory, not spread out in whatever spot memory happened to be available at the time. With cache misses being huge speed hits on modern processors, the effect of this on program execution times can't be discounted.

Iconoclast
Wednesday, July 14, 2004

I don't see how locality of reference is related to a G.C. A garbage collector is distinguished by the property of recovering memory that is no longer referenced.

Christopher Diggins
Wednesday, July 14, 2004

A "compacting" GC can move allocated blocks so that they're contiguous.

Christopher Wells
Wednesday, July 14, 2004

*  Recent Topics

*  Fog Creek Home