What properties are guaranteed by designers in Java?

I used to think that intuitively speaking, a constructor in Java is what an object does, and that nothing can touch that object until its constructor returns. However, I was wrong again and again in this:

All these facts violate my intuition of what I thought about the constructor.

I can no longer say with certainty what the Java constructor actually does, or what it is intended for use in. If I do a simple DTO with all trailing fields, then I can understand what using a constructor is because it is exactly the same as a structure in C, except that it cannot be changed. Other than that, I don’t know which constructors can be reliably used for Java. Is it just a convention / syntactic sugar? (i.e. if there were only factories that initialize the objects for you, you would only have X x = new X() , and then change each field to x so that they do not have default values), given the above facts , it will be almost equivalent to how Java actually is)

I can name two properties that are actually guaranteed by the constructors: if I do X x = new X() , then I know that x is an instance of x , but not a subclass of x , and its final fields are fully initialized. You may be tempted to say that you know that the constructor x finished and you have a valid object, but this is not true if you pass x to another thread - the other thread may see an uninitialized version (i.e., that you just said no different from factory call guarantees). What other properties do designers really guarantee?

+6
source share
4 answers

All these facts violate my intuition of what I thought about the constructor.

They should not. The designer does exactly what you think.

1: uninitialized objects can be skipped by sharing this

3: Uninitialized objects may leak into another thread before they are fully built.

The problem with this leak, the start of threads in the constructor and saving the newly created object, where several threads access it without synchronization, is all the problems associated with reordering the initialization of non-competitive (and non-volatile) ones. But the initialization code is still executed by the constructor. The stream that built the object fully sees the object. This applies to when these changes are visible in other threads that are not guaranteed by the language definition.

You may be tempted to say that you know that the constructor of X is finished and you have a valid object, but this is not true if you pass X to another thread - the other thread may see an uninitialized version (that is, what you just said no different from factory call guarantees).

It is right. It is also correct that if you have an unsynchronized object and you mutate it in one thread, other threads may or may not see the mutation. This is the nature of threaded programming. Even designers are not protected from the need to correctly synchronize objects.

2: uninitialized objects can be skipped by a subclass receiving it from the finalizer

This document is about finalizers and improper access to an object after garbage collection. When hacking subclasses and finalizers, you can create an object that was not properly constructed, but this is a serious hack for this. For me, this does not somehow challenge what the constructor does. Instead, it demonstrates the sophistication of a modern, mature, JVM. The document also shows how you can write your code to get around this hack.

What properties are guaranteed by designers in Java?

By definition, the constructor:

  • Allocates space for an object.
  • Sets all instance variables in the object by default. This includes instance variables in object superclasses.
  • Assigns parameter variables to an object.
  • handles any explicit or implicit constructor call (calling this () or super () in the constructor).
  • Initializes variables in the class.
  • Performs the remainder of the constructor.

From the point of view of your 3 problems, # 1 and # 3, again, about when the initialization of non-final and non-volatile fields is visible by flows other than those that built the object. This visibility without synchronization is not guaranteed.

Problem # 2 shows a mechanism in which, if an exception occurs during constructor execution, you can override the finalize method to get an incorrectly constructed object. Constructor points 1-5 have occurred. With hacking, you can get around part 6. I think it’s in the eye of the beholder if it challenges the identity of the constructor.

+6
source

From the JLS 12.5 section:

12.5. Creating instances of a new class

Before a reference to a newly created object is returned as a result, the specified constructor is processed to initialize a new object using the following procedure:

Assign constructor arguments to the newly created parameter variables for this constructor call.

If this constructor starts with an explicit constructor invocation (§8.8.7.1) of another constructor in the same class (using this), then evaluate the arguments and process the constructor invocation recursively using these five steps. If this constructor call terminates abruptly, then this procedure terminates abruptly for the same reason; otherwise, go to step 5.

This constructor does not start by explicitly calling the constructor of another constructor in the same class (using this). If this constructor is intended for a class other than Object, then this constructor will begin with an explicit or implicit call to the constructor of the superclass (using super). Evaluate the arguments and handle the call to the superclass constructor recursively using these same five steps. If the constructor call terminates abruptly, then this procedure terminates abruptly for the same reason. Otherwise, go to step 4.

Run instance initializers and instance variable initializers for this class, assigning the values ​​of the instance variable to initializers to the corresponding instance variables, from left to right, in which they are displayed in text form in the source code for the class. If the execution of any of these initializers results in an exception, then no new initializers are processed, and this procedure terminates abruptly with the same exception. Otherwise, go to step 5.

Run the rest of the body of this constructor. If this execution completes abruptly, then this procedure terminates abruptly for the same reason. Otherwise, this procedure will complete normally.

**

Unlike C ++, the Java programming language does not specify modified rules for the> dispatch method when creating a new instance of the class. If a method is called that is overridden in subclasses in the initialized object, then these overriding methods are used, even before the new object is fully initialized.

And from JLS 16.9 :

Note that there are no rules that would allow us to conclude that V is definitely not assigned to the instance variable initializer. We can informally conclude that V is not specifically assigned the initializer of the instance variable C, but there is no need for such a rule to be explicitly stated.

It happens before 17.4.5 :

Threading 17.5.2 :

Reading the final field of an object inside the stream that builds this object is ordered relative to the initialization of this field inside the constructor in the usual case - before the rules. If reading occurs after the field is specified in the constructor, it sees the value specified by the final field, otherwise it sees the default value.

+1
source

The class contains constructors that are called to create objects from the class plan.

This is what Oracle is talking about designers.

Now to your point.

intuitively, a constructor in Java is what an object does, and that nothing can touch that object until its constructor returns.

So, according to the official documentation, your assumption is wrong. And points 1 and 2 are an abuse of the rules and behavior of Java, if you do not want to filter through your objects! Since it is also not related to Constructor , I will skip the discussion of these issues.

Now, if we are talking about your 3rd point, there is nothing in a multi-threaded environment that could guarantee you the consistency of your code, if only “correctly synchronized blocks” or “atomic instructions”. Since creating an object is not a synchronized or atomic instruction, there is no guarantee of being consistent! The Constructor cannot do anything with it. In other words, it is not Constructor responsibility to create your atomic object.

Now the answer to your question "What other properties do the designers really guarantee?" somewhat easier. Constructors are simply nothing but special types of methods that are called when an object is created from the blue fingerprint of the class. Thus, he can not guarantee anything if you do not give him the opportunity to be executed sequentially, like any other methods. After sequential execution, it can guarantee you that your object will be created and initialized at your request and instructed in it.

0
source
Constructors

are java, which are simply used to initialize the state of the created object ... more.

-1
source

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


All Articles