On Tue, 10 Jan 2023 23:45:59 GMT, Maurizio Cimadamore <mcimadam...@openjdk.org> 
wrote:

>> It's slightly different from that.
>> 
>> Considering any of the various things in scope that can point to an object 
>> (these are: the current 'this' instance, the current outer 'this' instance, 
>> method parameter/variable, method return value, top of Java stack), such a 
>> thing has a "direct" reference if it might possibly _directly_ point to the 
>> 'this' we're tracking, while a thing has an "indirect" reference if it might 
>> possibly point to the 'this' we're tracking through _at least one level of 
>> indirection_.
>> 
>> This is just an attempt to eliminate some false positives by distinguishing 
>> between those two cases. Originally I was going to try to track fields (in a 
>> very limited way), and so this distinction was going to be more important, 
>> but even without tracking fields it's still useful. For example, if some 
>> method invokes `x.y.foo()` and `x` represents a direct but not an indirect 
>> 'this' reference, then there is no leak declared.
>> 
>> Considering the other options... (a) if you only track direct references, 
>> then you suffer from more false negatives (how many? unclear); (b) if you 
>> lump direct and indirect references into one bucket, then you suffer from 
>> more false positives (as in previous example `x.y.foo()`).
>> 
>> You can see an example of an indirect reference being tracked and exposed in 
>> the unit test `ThisEscapeArrayElement.java`.
>> 
>> Another motivating example is lambdas. The act of simply _creating_ a lambda 
>> never creates a leak, and a lambda never represents a _direct_ reference. 
>> But it might represent an _indirect_ reference.
>
> So, if I understand correctly your array element test, when we have `new 
> Object[][] { { this } }` the analysis is able to detect that there might be 
> some direct reference nested inside the array. So the outer array is an 
> indirect reference. The inner array is also an indirect reference - but any 
> element accessed on the inner array are direct reference - and so you detect 
> a leak there. Correct?

Yes - although it's not tracked being tracked any more precisely than "one or 
more levels of indirection".

And of course by "reference" we only mean "the possibility of a reference" - in 
general we don't know for sure.

Here's the logic:
* The analysis knows `this` is a direct reference
* Therefore the array expression `{ this }` has an indirect reference (but no 
direct reference)
* The outer array expression `{ { this } }` therefore _also_ has an indirect 
reference (but no direct reference)

At this point, we don't know how many levels of indirection there are in 
`array` though.... only that its ≥ 1.

* There expression `array[0]` therefore is determined to have both direct and 
indirect references (they are both _possible_ because we've dereferenced 
something with an indirect reference)
* As does `array[0][0]` for the same reason

So invoking `array[0][0].hashCode()` means invoking `hashCode()` on something 
that has a possible direct reference, and is therefore a leak.

Note that because of the imprecision in the number of levels of indirection, 
invoking `array[0].hashCode()` would also have generated a warning - but in 
that case, a false positive.

-------------

PR: https://git.openjdk.org/jdk/pull/11874

Reply via email to