Is self-esteem in the constructor considered an "escape"?

Reading this article about JSR-133, it says:

all entries in the final fields (and variables reachable indirectly through these final fields) become "frozen", ...

If the reference to the object cannot be deleted during construction, then as soon as the constructor completes and the thread publishes a reference to the object, the final fields of the object are guaranteed to be visible ...

One of the caveats with initialization security is that the link object should not "run away" from its constructor - the constructor should not publish, directly or indirectly, a link to the object being built.

My question is what is considered an escape. In particular, I want to know if this (somewhat artificial and strange) code leads to a child-safe Child object:

class Parent { /** NOT final. */ private int answer; public int getAnswer() { return answer; } public void setAnswer(final int _answer) { answer = _answer; } } public class Child extends Parent { private final Object self; public Child() { super.setAnswer(42); self = this; } @Override public void setAnswer(final int _answer) { throw new UnsupportedOperationException(); } } 
  • First, while Parent is explicitly modified, Child is "virtually unchanged" because the parent setter that would allow the change is no longer available.
  • The reference to "this" in the constructor is not visible to anyone (not getter, and is not passed to any other object). So, is this considered an "escape"?
  • But the object as a whole refers to the final field (self), and therefore theoretically it should be "frozen". OTOH, the last field is not available in itself, so it may not be considered; I could well imagine that JIT is fully optimizing it.
  • If "self" was accessible via getter, but getter is not called in the constructor, then it is considered a reset (if it was not before)? This would prevent JIT from optimizing it so that it would then “count”, maybe?

So, is the child “safe to publish”, and if not, why, and will the getter for the “I” change the answer?

If the purpose of the question is not clear, I think that if it works, it will make it easy to make the volatile class “safe-public” by simply extending it as shown above.

+6
source share
1 answer

Perhaps you misunderstand the meaning of escape. The fact is that this value should not reach any code foreign to the constructor. I think a few examples will explain this better:

  • setting a private field in this not considered an escape code;
  • calling a private method, which, in turn, does not call any additional methods and does not assign the variable this variable of a foreign object, is not considered an escape code;
  • a call to a public, overridden method owned by this is counted if the class is final . Therefore, your code skips this when calling setAnswer , and not when assigning this to self . What for? Because a subclass can override this method and publish this for any external code.

A note on your reasoning about self : self achievable with this , and it does not depend on the fact that the foreign caller cannot get its value. It is enough that the method can internally dereference it. In any case, the freezing rules do not take into account the level of access of the variables. For example, everything is accessible through reflection.

+4
source

Source: https://habr.com/ru/post/974509/


All Articles