• Post Reply Bookmark Topic Watch Topic
  • New Topic

How does finalize() work in a class?  RSS feed

 
David Tyson
Greenhorn
Posts: 11
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi all, I'm new to java and am reading through the Thinking in Java 4th edition book. I came across the method 'finalize()' which should be called whenever an object is about to be garbage collected, so I decided to try it out. Here is my code:



The odd thing about this is when I run the program, it seems to be random regarding as to whether or not finalize() is run. In this case, I would expect it to output 'Bye!' 3 times from the 1st, 2nd and 3rd smurf because there are no more references to them. However, what I get instead is sometimes no 'Byes', sometimes 1, or sometimes 2. I haven't yet got 'Byes' from all 3 of them. Can anyone give me some insight, possibly from the gc point of view, into what is happening here?

[Edit - added code tags - MB]
 
Jeff Verdegan
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
1) You will never call it directly. It's called by the JVM as part of the GC process.

2) You can't really predict when or even if GC will run, other than by trying to allocate more heap than the JVM has available. Therefore, you can' rely on finalize() being called on a particular schedule, or even on it being called at all in the general case.


3) You will probably never need to override or even think about the finalize() method. If you want a last-ditch, best-effort, catch-all-in-case-the-user-forgot-to-clean-up resource release mechanism, use a PhantomReference. Note, however that neither finalize() nor PhantomReference should be relied upon, and they should not be used as the primary cleanup mechanism. They are tied to GC, which is for reclaiming memory and knows nothing about whatever other resources you may be cleaning up, and so may not run even if those resources are exhausted. If something needs to be cleaned up, it's up to your class to document that and it's up to the user of your class to do it.

4) Starting in Java 7, there's a language-level mechanism to do some degree of automated cleanup. I think I've seen the phrase "with resource" or something like that.
 
David Tyson
Greenhorn
Posts: 11
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks for your reply! I'm more at a stage of learning the language than writing an actual program for it so I'm just testing stuff out at the minute.

I know the gc isn't guaranteed to run, but doesn't the line

System.gc();

force it to run? So this makes the gc collect up the 3 unreferenced Smurfs and calls their finalize method?
 
Joanne Neal
Rancher
Posts: 3742
16
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
David Tyson wrote:I know the gc isn't guaranteed to run, but doesn't the line

System.gc();

force it to run?

From the javadoc (my emphasis)
Calling the gc method suggests that the Java Virtual Machine expend effort toward recycling unused objects

There is no requirement for garbage collection to be run when the gc() method is called. And in a program that uses as little memory as yours, it's less likely that it will. And in a program as short as yours it's more likely that the JVM will exit without doing any garbage collection.
 
David Tyson
Greenhorn
Posts: 11
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ah... so .gc() only suggests the garbage collector be run.

Just one more niggle... why is there a randomness factor? It's a small program with no user input - everytime the JVM opens to run the program, shouldn't the initial conditions, like memory available, be the same? So why isn't the output 'deterministic'?
 
Jeff Verdegan
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
David Tyson wrote:Ah... so .gc() only suggests the garbage collector be run.

Just one more niggle... why is there a randomness factor? It's a small program with no user input - everytime the JVM opens to run the program, shouldn't the initial conditions, like memory available, be the same? So why isn't the output 'deterministic'?


There's a lot of other stuff happening on your computer besides your app. Web browser, text editor or IDE, IM, etc., plus the OS has lots of its own bookkeeping to do. All those things are asking for varying amounts of memory, CPU, and disk at varying times, and your app's main thread and the JVM's GC thread have to share the system's resources with all those other things. There are very many largely independent pieces interacting in very complex ways. So even if it's deterministic, I wouldn't realistically expect it to be predictable or consistent. Not to mention the fact that some scheduling algorithms deliberately have a randomness factor built into them.
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
David Tyson wrote:...It's a small program with no user input - everytime the JVM opens to run the program, shouldn't the initial conditions, like memory available, be the same? So why isn't the output 'deterministic'?

Strangely enough, I suspect the fact that your program is small makes the gc less likely to run since, as Jeff pointed out, it has to compete with other stuff on your system. It therefore makes sense that it only runs when it needs to, or when it has a good chance of reclaiming a lot of space. That said, I regard it as a black box, and I could be totally wrong.

So the facetious answer to your original question is: not very well - and quite a lot of books suggest that you don't use finalize() at all.

Also, you can almost always avoid it by adding your own explicit "finalizer" method, which seems to be the preferred approach for resource-hungry objects like java.sql.Connection (see its close() method). You can even put a call to it in a finalize() if you're really paranoid, and that approach does have some merit.

Winston
 
David Tyson
Greenhorn
Posts: 11
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ah, thank you... it makes perfect sense now!
 
Brian Burress
Ranch Hand
Posts: 131
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
David,

Though you are clear, I'll submit a somewhat trivial tweak to your main class which can help you see some of the behaviour of the finalize being called. You may need to increase the counter in the for loop if you don't see any "Bye!" until after the loop terminated appears, but I am assuming you'll see some "Bye!"'s mixed in with the "Hello!"'s when you run it.


 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!