DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
  1. DZone
  2. Coding
  3. Java
  4. Java's Finalizer Is Still There

Java's Finalizer Is Still There

It's commonly said not to rely on finalizers, often without real world examples. See how one dev dealt with finalizers and the issues they caused on a project.

Dustin Marx user avatar by
Dustin Marx
·
Mar. 06, 17 · Tutorial
Like (12)
Save
Tweet
Share
19.63K Views

Join the DZone community and get the full member experience.

Join For Free

When I was first transitioning from C++ to Java, I remember being told repeatedly and frequently reading that one should not treat the Java finalizer like C++ destructors and should not count on them. The frequency and insistent nature of this advice had such an effect on me that I cannot recall the last time I wrote a finalize() method, and I cannot recall ever having written one in all the years I've written, read, reviewed, maintained, modified, and debugged Java code. Until recently, however, the effects of finalize() were not something I thought much about, probably because I have not used finalize(). But a recent experience with finalize() has moved the effects of Java finalizers from an "academic exercise" to a real issue "in the wild."

The method-level Javadoc document comment for Object.finalize() provides some interesting details on the Java finalizer. It begins by providing an overall description of the method, "Called by the garbage collector on an object when garbage collection determines that there are no more references to the object. A subclass overrides the finalize method to dispose of system resources or to perform other cleanup." Another portion of this Javadoc comment warns of a couple issues commonly associated with use of Java finalizers: "The Java programming language does not guarantee which thread will invoke the finalize method for any given object. It is guaranteed, however, that the thread that invokes finalize will not be holding any user-visible synchronization locks when finalize is invoked. If an uncaught exception is thrown by the finalize method, the exception is ignored and finalization of that object terminates."

Josh Bloch devotes an item in Effective Java to the subject of Java finalizers. Item 7 of Effective Java's Second Edition is titled simply and concisely, "Avoid finalizers." Although many of the items in Effective Java use verbs such as "Prefer" or "Consider," this item uses the stronger verb "Avoid." Bloch does outline some examples where finalizers might be used, but his description of the inherent issues that remain and the many things to consider to mitigate those issues persuade most of us to avoid them as much as possible.

Bloch starts Effective Java item "Avoid Finalizers" with the emphasized (in bold) statement, "Finalizers are unpredictable, often dangerous, and generally unnecessary." Bloch emphasizes that developers should "never do anything time-critical in a finalizer" because "there is no guarantee [Java finalizers will] be executed promptly" and he emphasizes that developers should "never depend on a finalizer to update critical persistent state" because there is "no guarantee that [Java finalizers will] get executed at all." Bloch cites that exceptions in finalizers are not caught and warns of the danger of this because "uncaught exceptions can leave objects in a corrupt state."

The negative effect of Java finalizers that I had my recent experience with is also described by Bloch. His "Avoid Finalizers" item emphasizes (in bold), "there is a severe performance penalty for using finalizers" because it takes considerably longer "to create and destroy objects with finalizers." In our case, we were using a third-party library that internally used Java class finalize() methods to deallocate native memory (C/C++ through JNI). Because there was a very large number of these objects of these classes with finalize() methods, it appears that the system thread that handles Java finalization was getting behind and was locking on objects it was finalizing.

Garbage collection was also impacted adversely, with the collector kicking off more frequently than we'd normally see. We realized quickly that the garbage collection logs were indicating garbage collection issues that were not easily traceable to typical heap size issues or memory leaks of our own classes. Running the highly useful jcmd against the JVM process with jcmd <pid> GC.class_histogram helped us to see the underlying culprit quickly. That class histogram showed enough instances of java.lang.ref.Finalizer to warrant it being listed third from the top. Because that class is typically quite a bit further down the class histogram, I don't even typically see it or think about it. When we realized that three more of the top eight instances depicted in the class histogram were three classes from the third-party library and that they implemented finalize() methods, we were able to explain the behavior and lay blame on the finalizers (four of the top eight classes in the histogram made it a pretty safe accusation).

The Java Language Specification provides several details related to Java finalizers in Section 12.6 ("Finalization of Class Instances"). The section begins by describing Java finalizers: "The particular definition of finalize() that can be invoked for an object is called the finalizer of that object. Before the storage for an object is reclaimed by the garbage collector, the Java Virtual Machine will invoke the finalizer of that object." Some of the intentionally indeterminate characteristics of Java finalizers described in this section of the Java Language Specification are quoted here (I have added any emphasis):

  • "The Java programming language does not specify how soon a finalizer will be invoked."
  • "The Java programming language does not specify which thread will invoke the finalizer for any given object."
  • "Finalizers may be called in any order, or even concurrently."
  • "If an uncaught exception is thrown during the finalization, the exception is ignored and finalization of that object terminates."

I found myself enjoying working with the team that resolved this issue because I was able to experience in "real life" what I had only read about and knew about in an "academic" sense. It is always satisfying to apply a favorite tool (such as jcmd) and to apply previous experiences (such as recognizing what looked out of place in the jcmd class histogram) to resolve a new issue.

Java (programming language) Finalizer

Published at DZone with permission of Dustin Marx, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • DZone's Article Submission Guidelines
  • How to Submit a Post to DZone
  • API Design Patterns Review
  • Microservices Discovery With Eureka

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: