Why not block a value-based class

The docs say you shouldn't block an instance of a Java class based on values ​​like Optional , because the code

can give unpredictable results if it tries to distinguish two references to equal values ​​of a class based on a value ... indirectly through a synchronization call ...

Why shouldn't Java value-based classes be serialized? approves

Because future JVM implementations may not use object headers and reference pointers for value-based classes, some of the limitations are clear. (For example, do not block an identifier that the JVM should not support. A link to which is blocked can be deleted and replaced by another later, which makes releasing the lock meaningless and will cause deadlocks).

those. that the ban is the future. But there are no references to this statement.

If future verification is the basis, I would like to receive a link to it. If not, I would like to understand what a framework is, since value-based objects are Object s.

EDIT

By the way, I understand the reasons for not blocking integer and other primitive wrapper classes; they can be cached. But I cannot find documentation that the same applies to value-based classes, while Integer, &, etc. based on values, they are not value classes . I.E. Javadocs optional etc. frankly

This is a value based class.

The same does not apply to Integer , & etc.

+6
source share
3 answers

Here's what Nikolai Parlog writes about values-based classes on his blog:

In Java 8, value types are preceded by value-based classes. Their exact relation in the future is unclear, but it may be the same as with boxed and without boxed primitives (for example, Integer and int). In addition, the compiler can freely switch between them to improve performance. It is the switching back and forth, that is, the removal and subsequent re-creation of the link, that also prohibits applying mechanisms based on identity to classes based on values.

So Nikolay says this:

  • In the future, compilers may do things that transparently translate between values ​​and value-based classes in ways that do not preserve the identity of the object.

  • Certain things ("identity-based mechanisms") depend on the identity of the object. Examples include semantics == for links, an identifier hash code, primitive lock and object serialization.

  • For these things, it is likely that a transparent translation will not be transparent.

In the case of primitive locking, the problem is this:

  1. An instance of the value-based class is created.
  2. The instance is converted to a value behind the scene.
  3. Then the value is converted back to give another object.

If the two threads then use the "instance" as a primitive lock, they may not know that there are actually two objects (now). If they then tried to synchronize , they would (could) block different objects. This would mean that there was no mutual exclusion from the state that the lock was supposed to protect.

Unless you block a value-based class, you don't have to worry about this potential danger ... in the future.

But note that posting on Nikolai’s blog is one assumption about what could happen in Java 10 or later.


By the way, I understand the reasons for not blocking Integer and other classes of primitive shells; they can be cached.

Caching is not a problem as such, but a mechanism that causes the problem. The real problem is that it is difficult to determine the identity of the object of the lock object and, therefore, whether the lock mode is reliable.

With primitive shells, it is the semantics of packaging and unpacking that creates the uncertainty of the identity of the object. Subsequently, the conversion of an object <-> of an object of type mooted will be another source of this uncertainty.


The above blog is based on The State of Values, April 2014. John Rose, Brian Goetz, and Guy Steele talk about adding value types to a future version of Java. This note is an expression of position, not a fully specified (and accepted) sentence. However, the note gives us this hint:

"Many of the above restrictions correspond to the restrictions for so-called value-based classes. In fact, it seems likely that the boxed form of each type of value will be a value-based class."

which can be construed as implying a relationship between value types and existing value-based classes. (Especially if you read between value lines of Java 8 value- based classes .)


UPDATE - 2019/05/18

Value types did not get into Java 12, and they are not (yet) in the list for Java 13.

However, it’s already possible to demonstrate the problem associated with the problem referred to in the blog post:

  public class BrokenSync { private final Integer lock = 1; public void someMethod() { synchronized (lock) { // do something } } } 

The problem is that each BrokenSync instance will create an Integer instance using BrokenSync 1 . But JLS says that Integer objects created by the autobox are not necessarily separate objects. This way you can get all BrokenSync instances using the same Integer object as a lock.

+8
source

The lock is associated with the object. If the object is shared, the lock can be split. Immutable value classes can be used together. Theoretically, all references to an object of value that has a specific semantic meaning can refer to one common object. Typically, code is created for value objects to reuse value objects. For example, caching previously created values. Therefore, when you reference a value object, your code should work correctly, even if the value object is also used elsewhere. Therefore, do not use it to lock.

0
source

All the necessary information is directly on the page that you are quoting under the name “Value Based Classes”, although it is not written as clearly as it could be, and it does not use some magic phrases that could clarify these problems.

The magic phrase that I would use to describe this situation is that value-based classes can have behavior defined by the implementation . What the page says is that these classes do not use the reference equality == . He does not say that the implementation cannot define such an operator, but, in essence, he says "we are not talking about this." One of the phrases used is “make no obligation,” which is a little clearer.

For example, one of the implementations may, for convenience, say, make class V value-based, behave like most other objects, and not interfere with the suppression of members that V does not use. Another may use value-based classes in different ways, using the same internal mechanism as for primitive wrapper classes. (If you are creating a virtual machine, you do not need to implement each class in Java.) As long as the VM meets all the requirements (or, if you want, the contracts) listed on this page, it has fulfilled its obligations to the user.

Now suppose you write code that blocks such an object. The lock was not written to deal with this situation, so it will do something, but it should not be serial from VM to VM.

To be specific in relation to your question, future validation is just a special case of behavior defined by implementation. As it is written today, it may not be as it is written tomorrow, even if both are legal.

0
source

All Articles