Java 8 expression evaluation sequence - java

I have a case like
MyClass.invoke( anObject.setSystem() );
Is there a guarantee that anObject.setSystem() will be called before MyClass is loaded? As the initialization code of MyClass depends on the result of anObject.setSystem().
It is running with Java 8. Any suggestions/hints would be appreciated. Many thanks

MyClass will be loaded and all of its static fields and static initializers will be initialized before MyClass.invoke() is called.
See JLS 12.14.1
A class or interface type T will be initialized immediately before the first occurrence of any one of the following:
T is a class and an instance of T is created.
T is a class and a static method declared by T is invoked. <------------ right here
A static field declared by T is assigned.
A static field declared by T is used and the field is not a constant variable (§4.12.4).
T is a top level class (§7.6), and an assert statement (§14.10) lexically nested within T (§8.1.3) is executed.
EDIT
Thanks to #Holger and #gigi's comments, there was still the question as to whether the invocation that triggers the loading of the class occurs before or after the evaluation of the argument expression passed into it. I think the answer to that is in JLS 15.12.4, which states,
At run time, method invocation requires five steps. First, a target reference may be computed. Second, the argument expressions are evaluated. Third, the accessibility of the method to be invoked is checked. Fourth, the actual code for the method to be executed is located. Fifth, a new activation frame is created, synchronization is performed if necessary, and control is transferred to the method code.
The evaluation of argument expressions (step 2) occurs before the code to execute the method is located, (step 4, which probably results in the class being loaded and statically initialized) and only then, in the final step, is the static method invoked.

Related

static block execution before interpretation of bytecode.how?

When we say java Test, class loaders will load .class files into method area and static variables if any are initialized to corresponding values assigned and static blocks will be executed.
In java execution means code has to be interpreted by java interpreter. But how static block executes here without interpretation? It is still in a class loading phase, isn’t it?
But in most of the blogs and videos they say once after class loading completes, new thread will be created and it will look for main method and starts executing it. Interpreter comes to picture once main method starts execution in all blogs I saw.
class Test {
static int x = 10;
static {
int y = 10;
System.out.println(x);
}
public static void main(String[] args) {
}
}
The existence of an interpreter is an implementation detail that is irrelevant for describing the behavior of a program. In principle, it is possible to have a JVM without an interpreter at all, as it could have only a compiler that translates all byte code to native code before executing, and still implement the correct behavior. Current desktop and server JVMs have both, executing the code in a mixed mode.
So, it is also irrelevant at which point blogs and videos mention the existence of an interpreter as a way to execute the code, the execution of code always implies the existence of technical means to execute the code, like an interpreter or compiler.
The actual behavior has been specified in The Java Language Specification, §12.4.1:
§12.4.1. When Initialization Occurs
A class or interface type T will be initialized immediately before the first occurrence of any one of the following:
T is a class and an instance of T is created.
A static method declared by T is invoked.
A static field declared by T is assigned.
A static field declared by T is used and the field is not a constant variable (§4.12.4).
T is a top level class (§7.6) and an assert statement (§14.10) lexically nested within T (§8.1.3) is executed.¹
When a class is initialized, its superclasses are initialized (if they have not been previously initialized), as well as any superinterfaces (§8.1.5) that declare any default methods (§9.4.3) (if they have not been previously initialized). Initialization of an interface does not, of itself, cause initialization of any of its superinterfaces.
¹ this last bullet has been removed from newer specifications
Since the invocation of the main method is an invocation of “a static method declared by” your class, it implies the initialization of that class before the invocation. As you can derive from the last section, if the class containing the main method has uninitialized superclasses, they are initialized even before that class.
For the standard Java launcher, the order of events is
The main thread is created
The main thread loads the specified application class
The super classes of the application class are initialized, if not already initialized
The application class is initialized
The method static void main(String[]) is invoked on the application class
The terms “application class” and “main class” are interchangeable.
Note that this list is only meant to bring these events into the right order. There are far more events happening behind the scenes. Obviously, for asking the application class loader to load the application class, given by name, the classes String, Class, and ClassLoader must have been loaded and initialized, which also implies that their super class, Object has been initialized even before that. The existence of the main thread implies the loading and initialization of the class Thread. And all these classes use other classes behind the scenes.
You may run your application with the -verbose:class option to see which classes are already loaded before your application class.

Blocking Scoped outputs

I dont know whether this question has been asked before or not .I searched but couldn't find any duplicate question. If you find any related question please mention the link.
public class Exp
{
Exp()
{
System.out.println("Hello"); //3
}
{ System.out.println("Hello")}; //1
{ static{System.out.print("x");} //2
}
The order of printing of messages is 2,1,3.
What are the significance of these lines 1 & 2 and why that exec order
Line "1" is an instance initializer, which runs when an object is first created, before any constructors are called.
Line "2" is a static initializer, which runs when a class is first loaded, before any objects are created.
Section 12.5 of the JLS specifies when instance initializers are run:
Just before a reference to the newly created object is returned as the
result, the indicated constructor is processed to initialize the new
object using the following procedure:
Assign the arguments for the constructor to newly created parameter
variables for this constructor invocation.
If this constructor begins with an explicit constructor invocation
(§8.8.7.1) of another constructor in the same class (using this), then
evaluate the arguments and process that constructor invocation
recursively using these same five steps. If that constructor
invocation completes abruptly, then this procedure completes abruptly
for the same reason; otherwise, continue with step 5.
This constructor does not begin with an explicit constructor
invocation of another constructor in the same class (using this). If
this constructor is for a class other than Object, then this
constructor will begin with an explicit or implicit invocation of a
superclass constructor (using super). Evaluate the arguments and
process that superclass constructor invocation recursively using these
same five steps. If that constructor invocation completes abruptly,
then this procedure completes abruptly for the same reason. Otherwise,
continue with step 4.
Execute the instance initializers and instance variable initializers
for this class, assigning the values of instance variable initializers
to the corresponding instance variables, in the left-to-right order in
which they appear textually in the source code for the class. If
execution of any of these initializers results in an exception, then
no further initializers are processed and this procedure completes
abruptly with that same exception. Otherwise, continue with step 5.
Execute the rest of the body of this constructor. If that execution
completes abruptly, then this procedure completes abruptly for the
same reason. Otherwise, this procedure completes normally.
(emphasis mine)
The rest of the body of the constructor is executed after the instance initializer.
static blocks of a class are executed during class loading along with constants (static final members). 3 is invoked when the object is instantiated.
For you to understand better debug the code through your IDE to understand the sequence of execution.
See http://docs.oracle.com/javase/tutorial/java/javaOO/initial.html
A static initialization block is a normal block of code enclosed in braces, { }, and preceded by the static keyword. Here is an example:
static {
// whatever code is needed for initialization goes here
}
A class can have any number of static initialization blocks, and they can appear anywhere in the class body. The runtime system guarantees that static initialization blocks are called in the order that they appear in the source code.
The reason for the execution order is, in non-static block you might want to use static members, but in static block you cannot use non-static members. So it makes sense to execute static block first.
non-static block allows you to abstract the code that every constructor needs to execute, therefore it gets executed before constructor.
More detailed order of execution:
1.static block of superclass
2.static block of this class
3.non-static block of superclass
4.constructor of superclass
5.non-static block of this class
6.constructor of this class

Java static imports

Just by experiment I discovered that Java non static methods overrides all same named methods in scope even at static context. Even without allowing parameter overloading. Like
import java.util.Arrays;
import static java.util.Arrays.toString;
public class A {
public static void bar(Object... args) {
Arrays.toString(args);
toString(args); //toString() in java.lang.Object cannot be applied to (java.lang.Object[])
}
}
I can't find anything about this in spec. Is this a bug? If it isn't, are there any reasons to implement language like that?
UPD: Java 6 do not compile this example. The question is - why?
The explanation is simple although it doesn't change the fact that the behavior is highly unintuitive:
When resolving the method to be invoked the first thing the compiler does is find the smallest enclosing scope that has a method of the right name. Only then come other things like overload resolution and co in game.
Now what is happening here is that the smallest enclosing scope that contains a toString() method is class A which inherits it from Object. Hence we stop there and don't search farther. Sadly next the compiler tries to find the best fit of the methods in the given scope and notices that it can't call any of those and gives an error.
Which means never statically import methods with a name that is identical to a method in Object, because methods that are naturally in scope take precedence over static imports (the JLS describes method shadowing in detail, but for this problem I think it's much simpler to just remember that).
Edit: #alf kindly submitted the right part of the JLS that describes the method invocation for those who want the whole picture. It's rather complex, but then the problem isn't simple either so that's to be expected.
It is not an override. If it did work, this.toString() would still access the method of A instead of Arrays.toString as would be the case if overriding had occurred.
The language specification explains that static imports only affect the resolution of static methods and types:
A single-static-import declaration d in a compilation unit c of package p that imports a field named n shadows the declaration of any static field named n imported by a static-import-on-demand declaration in c, throughout c.
A single-static-import declaration d in a compilation unit c of package p that imports a method named n with signature s shadows the declaration of any static method named n with signature s imported by a static-import-on-demand declaration in c, throughout c.
A single-static-import declaration d in a compilation unit c of package p that imports a type named n shadows the declarations of:
any static type named n imported by a static-import-on-demand declaration in c.
any top level type (§7.6) named n declared in another compilation unit (§7.3) of p.
any type named n imported by a type-import-on-demand declaration (§7.5.2) in c.
throughout c.
Static imports do not shadow non-static methods or inner types.
So the toString does not shadow the non-static method. Since the name toString can refer to a non-static method of A, it does cannot refer to the static method of Arrays and thus toString binds to the only method named toString that is available in scope, which is String toString(). That method cannot take any arguments so you get a compile error.
Section 15.12.1 explains method resolution and would have to have been completely rewritten to allow shadowing of unavailable method names within static methods but not inside member methods.
My guess is that the language designers wanted to keep method resolution rules simple, which means that the same name means the same thing whether it appears in a static method or not, and the only thing that changes is which are available.
If you try following similar looking code then you will not get any compiler error
import static java.util.Arrays.sort;
public class StaticImport {
public void bar(int... args) {
sort(args); // will call Array.sort
}
}
The reason this compiles and yours doesn't is that the toString() (or any other method defined in class Object) are still scoped to Object class because of Object being the parent of your class. Hence when compiler finds matching signature of those methods from Object class then it gives compiler error. In my example since Object class doesn't have sort(int[]) method hence compiler rightly matches it with the static import.
I do not think it is a bug or something different from normal import. For example, in case of normal import, if you have a private class with the same name as imported one the imported one will not be reflected.

Class initialization and synchronized class method

In my application, there is a class like below:
public class Client {
public synchronized static print() {
System.out.println("hello");
}
static {
doSomething(); // which will take some time to complete
}
}
This class will be used in a multi thread environment, many threads may call the Client.print() method simultaneously. I wonder if there is any chance that thread-1 triggers the class initialization, and before the class initialization complete, thread-2 enters into print method and print out the "hello" string?
I see this behavior in a production system (64 bit JVM + Windows 2008R2), however, I cannot reproduce this behavior with a simple program in any environments.
In Java language spec, section 12.4.1 (http://java.sun.com/docs/books/jls/second_edition/html/execution.doc.html), it says:
A class or interface type T will be initialized immediately before the first occurrence of any one of the following:
T is a class and an instance of T is created.
T is a class and a static method declared by T is invoked.
A static field declared by T is assigned.
A static field declared by T is used and the reference to the field is not a compile-time constant (§15.28). References to compile-time constants must be resolved at compile time to a copy of the compile-time constant value, so uses of such a field never cause initialization.
According to this paragraph, the class initialization will take place before the invocation of the static method, however, it is not clear if the class initialization need to be completed before the invocation of the static method. JVM should mandate the completion of class initialization before entering its static method according to my intuition, and some of my experiment supports my guess. However, I did see the opposite behavior in another environment. Can someone shed me some light on this?
Any help is appreciated, thanks.
My understanding of the quoted text is that the class initialization process is completed (will be initialized) before a static method declared by T is invoked.
will be initialized implies that the initialization process has been started and has terminated.
So it shouldn't be possible (to my understanding) that, while the static initializer is executed because Thread A called print, another Thread already can call print.
Chapter 12.4.2 of the JLS describes the detailed initialization procedure, which takes care of initializing classes in a multithreaded environment.
Executing static blocks considered to be a part of class initialization:
Initialization of a class consists of executing its static initializers and the initializers for static fields (class variables) declared in the class...
It is guaranteed by JVM specification that that will be done in thread safe way. To quote JLS section 12.4.2 Detailed Initialization Procedure:
Because the Java programming language is multithreaded, initialization of a class or interface requires careful synchronization, since some other thread may be trying to initialize the same class or interface at the same time. There is also the possibility that initialization of a class or interface may be requested recursively as part of the initialization of that class or interface; for example, a variable initializer in class A might invoke a method of an unrelated class B, which might in turn invoke a method of class A. The implementation of the Java virtual machine is responsible for taking care of synchronization and recursive initialization...
In more detail, it's implemented by acquiring lock on Class object:
The procedure for initializing a class or interface is then as follows:
Synchronize (§14.19) on the Class
object that represents the class or
interface to be initialize
Your method is static synchronized and it requires lock on Class object as well. Since the same lock is acquired by JVM during class initialization it's not possible for one thread to initialize class and for other execute static synchronized method on it.
All quotes are taken from
JLS
I hope that's helpful. Btw, how do you know that print occurs before class initialization finishes?
EDIT: Actually I'm wrong about assumption that only static synchronized couldn't be executed in parallel with class initialization. Any methods on class couldn't be executed until class initialization finishes.
If your "multi thread environment" uses multiple class loaders to load your Client class it would be possible for you to get mulitple Client instances, each one of which would run the static initialiser prior to running any Client.print() calls. You would see something like
doSomething
hello
doSomething
hello
hello
hello
I have some sample code which shows this but the current version is a little fiddly to run. If you want I can clean it up and post it.
If the code is running in some containers such as Servlet, you could initialize it in container’s lifecycle.

Initialization of Java - Class v/s Interface

I am stuck at the below concept of initialization of java class and interface :
I read the following sentence in the below mentioned book :
An interface is initialized only because a non-constant field declared by the interface is used, never because a subinterface or class that implements the interface needs to be initialized.
But that isn't the case when we initialise any java class.
Thus, initialization of a class requires prior initialization of all its superclasses, but not its superinterfaces.
Initialization of an interface does not require initialization of its superinterfaces.
My question is Why is this so ?
Any help would be greatly appreciated !
Thanks
PS : Book - "Inside the Java Virtual Machine" by Bill Venners (Chapter 7 - LifeTime of a class )
The only things you can declare in an interface are method signatures and constant fields. The latter can be initialized using constant values (i.e. string literals, integers, etc., possibly in some combination) or using non-constant values (i.e. method calls). Thus if an interface doesn't have any non-constant fields, no initialization is required -- everything is known at compile time. If there are non-constant fields that are used by the program, initialization code must be run to ensure those fields are assigned a value.
Hope that helps.
P.S.: That chapter is available online here if anyone wants to read it in full.
To cite the Java language specification §12.4.1:
A class or interface type T will be
initialized immediately before the
first occurrence of any one of the
following:
T is a class and an instance of T is created.
T is a class and a static method declared by T is invoked.
A static field declared by T is assigned.
A static field declared by T is used and the reference to the field is not
a compile-time constant (§15.28).
References to compile-time constants
must be resolved at compile time to a
copy of the compile-time constant
value, so uses of such a field never
cause initialization.
Invocation of certain reflective
methods in class Class and in package
java.lang.reflect also causes class or
interface initialization. A class or
interface will not be initialized
under any other circumstance.
The intent here is that a class or interface type has a set of initializers that put it in a consistent state, and that this state is the first state that is observed by other classes.
Interesting. Let's see why superclass must be initialized before subclass.
class A
static x = DB.insert(1,...);
class B extends A
static y = DB.select(1);
The static initializer of a superclass can cause some side effects that the compiler cannot see, and the subclass may depend on such side effects.
However the same argument can apply to super interfaces. I don't see a hard reason why Java doesn't initialize super interfaces eagerly. Soft reasons are anybody's guess.
Give the rules as they are, we must be careful with field initialization in interfaces:
better not have any fields in an interface
otherwise, fields better be compile time constant only
otherwise, field initialization better not have any side effect.
otherwise, side effect must be only accessible through the field itself

Categories

Resources