I don't understand the "this-escape" warning under this context

Remi Forax forax at univ-mlv.fr
Sat Sep 30 05:45:17 UTC 2023


> From: "David Alayachew" <davidalayachew at gmail.com>
> To: "compiler-dev" <compiler-dev at openjdk.org>
> Sent: Saturday, September 30, 2023 5:22:09 AM
> Subject: I don't understand the "this-escape" warning under this context

> Hello Compiler Dev Team,

> I have the following code example.

> ```java

> package Paint;

> import javax.swing.*;

> public class GUI
> {

> private final JFrame frame;

> public GUI()
> {

> this.frame = new JFrame();

> this.frame.add(this.createBottomPanel());

> }

> private final JPanel createBottomPanel()
> {

> final JButton save = new JButton();

> save
> .addActionListener
> (
> actionEvent ->
> {

> this.toString();

> }

> )
> ;

> return null;

> }

> }
> ```

> This is the compile command that I used.

> ```
> javac -Xlint:all GUI.java
> ```

> When I compile, I get the following warning.

> ```
> GUI.java:16: warning: [this-escape] possible 'this' escape before subclass is
> fully initialized
> this.frame.add(this.createBottomPanel());
> ^
> GUI.java:28: warning: [this-escape] previous possible 'this' escape happens here
> via invocation
> actionEvent ->
> ^
> 2 warnings
> ```

> Can someone help me understand the what, why, and how of this warning? I don't
> understand it at all.

> I am pretty sure I understand the basic premise of "this-escape" -- a
> not-fully-initialized object (this) can "escape" from its constructor before
> completing initialization, usually causing bugs and security vulnerabilities.

> A good example of this is a constructor calling an overridable method. If a
> subclass overrides that method, it may expose the state or perform behaviour
> that it is not prepared to perform at that time, amongst other things.

> But I struggle to follow that logic for my example. Could someone walk me
> through this ?

The first error seems to be a false positive because as you said the method createBottomPanel() is private (BTW, all private methods can not be overriden so declaring a private method final is not really useful). 
The second error is due to the fact that the lambda can be called before the end of the constructor, the compiler is not smart enough to know if this is the case or not. 

The usual workaround is to create the GUI inside static methods, the constructor being a static factory named by example createGUI() and createBottomPanel() being declared static. 
If you need objects, pass them as parameter of the static methods, so they are known to be fully initialized. 

Apart for the bugs with subclassing, the problem of publication in a concurrency context, having a constructor that escapes "this" also prevents a class to be a value class. 

> Thank you for your time and help!
> David Alayachew

regards, 
Rémi 
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/compiler-dev/attachments/20230930/438c625b/attachment.htm>


More information about the compiler-dev mailing list