Finalizer being run while class still in use (escape analysis bug)

Martin Buchholz martinrb at
Wed Oct 10 00:51:39 UTC 2018

Search for calls to Reference.reachabilityFence(this); in the jdk sources.

On Tue, Oct 9, 2018 at 5:35 PM, David Holmes <david.holmes at>

> Hi Luke,
> Moving this over to hotspot-dev. If it is an issue with the JIT escape
> analysis then hotspot-compiler-dev would be the place to raise this. But a
> general finalization issue may hit GC and runtime as well, so I redirected
> to the broader hotspot-dev.
> Also note that finalizers can run while methods of a class instance are
> still in progress [1]
> "Optimizing transformations of a program can be designed that reduce the
> number of objects that are reachable to be less than those which would
> naively be considered reachable."
>  - this is one of the evil things about finalizers. So it may not be a
> bug, just surprising.
> Cheers,
> David
> [1]
> html#jls-12.6
> On 10/10/2018 10:27 AM, Luke Hutchison wrote:
>> A user of a library I maintain, ClassGraph, has reported that a finalizer
>> is being called on a class while methods of the class are still running,
>> indicating that the class, even though it overrides finalize(), is not
>> being correctly marked as GlobalEscape, so that escape analysis is trying
>> to garbage-collect the class too early. Is this mailing list the correct
>> place to report this bug?
>> Here is the Maven rule for ClassGraph (you will also need to add Scala
>> deps) -- you will need version 4.2.8, since I put a mitigation in place in
>> version 4.2.9:
>> <dependency>
>>      <groupId>io.github.classgraph</groupId>
>>      <artifactId>classgraph</artifactId>
>>      <version>4.2.8</version>
>> </dependency>
>> Here is the Scala code that reproduces the problem 100% of the time:
>> import io.github.classgraph.{ClassGraph, ClassInfo}
>> import scala.collection.JavaConverters._
>> import scala.compat.Platform.ConcurrentModificationException
>> while (true) {
>>    try {
>>      new ClassGraph().scan()
>>        .getResourcesMatchingPattern(".*".r.pattern)
>>        .asScala
>>        .map(_.getURL)
>>    } catch {
>>      case cme: ConcurrentModificationException =>
>>        cme.printStackTrace()
>>        throw cme
>>    }
>> }
>> Then start the JVM with -XX:+DoEscapeAnalysis
>> The code new ClassGraph().scan() returns a ScanResult, and then as soon as
>> ScanResult::getResourcesMatchingPattern is called with the ScanResult as
>> the invocation target, escape analysis sees that the ScanResult has "gone
>> out of scope" (despite the fact that the ScanResult is the invocation
>> target for a currently-running method), and immediately tries to garbage
>> collect it. This should not happen (1) since an invocation target should
>> never be marked for garbage collection while its methods are being run,
>> and
>> (2) since ScanResult overrides Object::finalize, so should have been
>> marked
>> as "GlobalEscape" by escape analysis.
>> The finalizer for the ScanResult class calls ScanResult::close, which
>> clears the allResources list:
>> 78697a727888457abb164311b8/src/main/java/io/github/
>> classgraph/
>> This results in a ConcurrentModificationException since
>> ScanResult::getResourcesMatchingPattern is still iterating through
>> allResources:
>> 78697a727888457abb164311b8/src/main/java/io/github/
>> classgraph/
>> I read somewhere (and it makes sense) that escape analysis is performed by
>> the compiler, so maybe this is a Scala bug, but this behavior is triggered
>> by the JVM switch -XX:+DoEscapeAnalysis , and I couldn't find any
>> references to escape analysis information in the Java classfile format
>> spec, so that leads me to think this may be a JVM bug (which is why I am
>> asking on this list).
>> Obviously having a garbage collector run a finalizer run while methods of
>> the object are still running is a very serious bug. Any pointers as to
>> where to report this issue would be appreciated. Thanks!

More information about the jdk-dev mailing list