Can we switch off finalizers?
Asked Answered
L

4

16

As there is little guarantee about when and even if finalizers run and finalizers are almost considered a smell nowadays - is there any way to persuade the JVM to completely skip all finalization processes?

I ask because we have a mammoth application which, when moved to a newer JVM (not sure which at this stage) is brought to its knees by what looks very much like the known problems with finalisers (exceptions being thrown and therefore very slow GC).

Added

There is some discussion on Troubleshooting a java memory leak: finalization? where it is suggested that the primary problem arises when exceptions are thrown within finalizers because that slows down the finalization process dramatically.

My issue shows as a dramatic slow-down when memory becomes low and analysis of heap dumps show a large number of Finalizer objects (over 10,000,000) - suggesting to me that the slowdown could be their fault because they are delaying the GC. Obviously I may be wrong.

I do not have the power to demand a refactor.

Latarsha answered 6/1, 2014 at 12:31 Comment(8)
Not that I know of, not without byte-code manipulation. I would suggest trying to refactor your application to remove the finalizers if you believe they are the issue.Chapnick
Do you think the application will work without the code in the finalizers running at some point? IIrc, finalizers will be run for every object collected during normal operation of the VM; exception: abrupt shutdown of the VM.Clunk
@HannoBinder Finalizers also make escape analysis impossible. So if application is heavy loaded they might be the cause.Pyrone
Very slow GC isn't likely due to exceptions -- it's likely due to lack of heap space.Hostler
I've added some further notes - would appreciate all suggestions offered.Latarsha
@HannoBinder - Yes I am - mostly because Java makes no promises about when, or even if finalizers are run so the code should survive that.Latarsha
Certainly the application logic will not suffer if finalizers are not run. - I'm rather thinking about resource de-allocations which, if never performed, may break the application through resource depletion. After all, that finalizer code was written for some reason. If it can be omitted completely, the assumption that lead to its implementation was erroneous; but if it does something useful, probably just at the "wrong" place, turning finalizer code off will break something.Clunk
@HannoBinder - You are too generous - I would say if you are relying on finalizers to clean up your mess you are an ..... expletive deleted.Latarsha
I
6

Is there any way to persuade the JVM to completely skip all finalization processes?

In a word No.

But unless a large proportion of your objects have finalize methods and/or the finalize methods are particularly expensive, I think that they are unlikely to make GC "very slow". I expect the problem is something else.

I suggest that you turn on GC logging to try and get a better picture of what is actually happening.

But I also agree, that refactoring the code to get rid of the finalize() methods would probably be a good thing in the long run. (There are very few situations where using finalize is genuinely the best solution.)


UPDATE - your new evidence is pretty convincing, though not a proof!.

I do not have the power to demand a refactor.

Then, I suggest you place the evidence at the feet of the people who do :-).

Alternatively, you could add an exception handler to the suspect finalize methods to see if they are throwing exceptions. (And if they are, then change them to avoid the exceptions being thrown ...)

But the bottom line is that if finalization is the real cause of your performance problems then the best (and probably the only) way to cure them is to change the code.

Ineradicable answered 6/1, 2014 at 14:54 Comment(0)
C
3

Java 18 (released in 2022) deprecated finalization for removal with JEP 421 and added an option for disabling it.

You can now start your application with --finalization=disabled and it won't run finalizers.

java --finalization=disabled -jar your-app.jar

The JEP also mentions a JFR event called jdk.FinalizerStatistics which gives you more information about finalization:

# start Java with the JFR event jdk.FinalizerStatistics enabled
java -XX:StartFlightRecording:filename=recording.jfr -jar your-app.jar
# print events
jfr print --events FinalizerStatistics recording.jfr
Chas answered 15/5, 2023 at 14:52 Comment(0)
S
2

It is possible to suppress finalization on certain objects. It does not require bytecode manipulation as one commenter noted.

The procedure is described here and source code is provided. The class java.lang.ref.Finalizer is responsible for maintaining a list of objects that have not yet been finalized. To suppress finalization of your objects of interest, it suffices to use reflection APIs to acquire a lock on the field lock, iterate over the linked list unfinalized that the Finalizer class maintains, and remove your object from this list.

I've tried this method to safely instantiate custom-serialized objects while bypassing constructor invocation, and avoiding problems when the finalizer would be invoked with normal GC. Before applying this method my JVM would break with hard faults in the finalizer thread; since applying this method the faults do not occur.

Sorilda answered 27/6, 2017 at 12:35 Comment(0)
N
0

You cannot switch off finalizer in java, but all you can do is write code that will facilitate GC :-).

Nord answered 7/1, 2014 at 3:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.