Execution of Java Program
This section specifies activities that occur during execution of a Java program.
It specifies the detailed procedures used in starting up the virtual machine, class and interface type loading, linking, and initialization. It then specifies the procedures for creation of new class instances. It concludes by describing the unloading of classes and the procedure followed when a virtual machine exits.
Virtual Machine Start-upA Java Virtual Machine starts execution by invoking the method main of some specified class, passing it a single argument, which is an array of strings.
This causes the specified class to be loaded, linked to other types that it uses, and initialized.
The method main must be declared public, static, and void.
In Sun's JDK implementation on UNIX, the command line
Java Robo Shakanr Rajani Aishwarya Sun
will start a Java Virtual Machine by invoking the method main of class Robo (a class in an unnamed package), passing it an array containing the four strings "Shankar", "Rajani", "Aishwarya", and "Sun".
We now outline the steps the virtual machine may take to execute Robo, as an example of the loading, linking, and initialization processes that are described further in later sections.
The initial attempt to execute the method main of class Robo discovers that the class Robo is not loaded-that is, the virtual machine does not currently contain a binary representation for this class. The virtual machine then uses a ClassLoader to attempt to find such a binary representation. If this process fails, an error is thrown.
Loading:
Loading refers to the process of finding the binary form of a class or interface type with a particular name, perhaps by computing it on the fly, but more typically by retrieving a binary representation previously computed from source code by a compiler and constructing, from that binary form, a Class object to represent the class or interface. The binary format of a class or interface is normally the class file format
If an error occurs during class loading, then an instance of one of the following subclasses of class LinkageError will be thrown at any point in the Java program that (directly or indirectly) uses the type:
• ClassCircularityError: A class or interface could not be loaded because it would be its own superclass or superinterface ..
• ClassFormatError: The binary data that purports to specify a requested compiled class or interface is malformed.
• NoClassDefFoundError: No definition for a requested class or interface could be found by the relevant class loader.
Linking: Verification, Preparation, and Resolution
Linking is the process of taking a binary form of a class or interface type and combining it into the runtime state of the Java Virtual Machine, so that it can be executed. A class or interface type is always loaded before it is linked. Three different activities are involved in linking: verification, preparation, and resolution of symbolic references.
Java allows an implementation flexibility as to when linking activities (and, because of recursion, loading) take place, provided that the semantics of the language are respected, that a class or interface is completely verified and prepared before it is initialized, and that errors detected during linkage are thrown at a point in the program where some action is taken by the program that might require linkage to the class or interface involved in the error.
Verification ensures that the binary representation of a class or interface is structurally correct. For example, it checks that every instruction has a valid operation code; that every branch instruction branches to the start of some other instruction, rather than into the middle of an instruction; that every method is provided with a structurally correct signature; and that every instruction obeys the type discipline of the Java language.
If an error occurs during verification, then an instance of the following subclass of class LinkageError will be thrown at the point in the Java program that caused the class to be verified:
• VerifyError: The binary definition for a class or interface failed to pass a set of required checks to verify that it obeys the semantics of the Java language and that it cannot violate the integrity of the Java Virtual Machine.
Preparation involves creating the static fields for a class or interface and initializing such fields to the standard default values . This does not require the execution of any Java code; explicit initializers for static fields are executed as part of initialization , not preparation.
Java implementations must detect the following error during preparation:
• AbstractMethodError: A class that is not declared to be abstract has an abstract method. This can occur, for example, if a method that is originally not abstract is changed to be abstract after another class that inherits the now-abstract method declaration has been compiled.
A Java binary file references other classes and interfaces and their fields, methods, and constructors symbolically, using the fully qualified names of the other classes and interfaces. For fields and methods these symbolic references include the name of the class or interface type which declares the field or method, as well as the name of the field or method itself, together with appropriate type information.
Before a symbolic reference can be used it must undergo resolution, wherein a symbolic reference is checked to be correct and, typically, replaced with a direct reference that can be more efficiently processed if the reference is used repeatedly.
If an error occurs during resolution, then an instance of one of the following subclasses of class IncompatibleClassChangeError, or of some other subclass, or of IncompatibleClassChangeError itself (which is a subclass of the class Linkage-Error) may be thrown at any point in the Java program that uses a symbolic reference to the type:
• IllegalAccessError: A symbolic reference has been encountered that specifies a use or assignment of a field, or invocation of a method, or creation of an instance of a class, to which the code containing the reference does not have access because the field or method was declared private,protected, or default access (not public), or because the class was not declared public. This can occur, for example, if a field that is originally declared public is changed to be private after another class that refers to the field has been compiled.
• InstantiationError: A symbolic reference has been encountered that is used in a class instance creation expression, but an instance cannot be created because the reference turns out to refer to an interface or to an abstract class. This can occur, for example, if a class that is originally notabstract is changed to be abstract after another class that refers to the class in question has been compiled.
• NoSuchFieldError: A symbolic reference has been encountered that refers to a specific field of a specific class or interface, but the class or interface does not declare a field of that name (it is specifically not sufficient for it simply to be an inherited field of that class or interface). This can occur, for example, if a field declaration was deleted from a class after another class that refers to the field was compiled.
• NoSuchMethodError: A symbolic reference has been encountered that refers to a specific method of a specific class or interface, but the class or interface does not declare a method of that name and signature (it is specifically not sufficient for it simply to be an inherited method of that class or interface). This can occur, for example, if a method declaration was deleted from a class after another class that refers to the method was compiled
Initialization
Initialization of a class consists of executing its static initializers and the initializers for static fields declared in the class. Initialization of an interface consists of executing the initializers for fields declared in the interface.
Before a class is initialized, its superclass must be initialized, but interfaces implemented by the class need not be initialized. Similarly, the superinterfaces of an interface need not be initialized before the interface is initialized
• Before a class is initialized its superclasses are initialized, if they have not previously been initialized.
• Initialization of an interface does not, of itself, require initialization of any of its superinterfaces.
Creation of New Class Instances
A new class instance is explicitly created when one of the following situations occurs:
• Evaluation of a class instance creation expression creates a new instance of the class whose name appears in the expression.
• Invocation of the newInstance method of class Class creates a new instance of the class represented by the Class object for which the method was invoked.
A new class instance may be implicitly created in the following situations:
• Loading of a class or interface that contains a String literal may create a new String object to represent that literal. This may not occur if the same String has previously been interned.
• Execution of a string concatenation operator that is not part of a constant expression sometimes creates a new String object to represent the result. String concatenation operators may also create temporary wrapper objects for a value of a primitive type .
Each of these situations identifies a particular constructor to be called with specified arguments (possibly none) as part of the class instance creation process.
Whenever a new class instance is created, memory space is allocated for it with room for all the instance variables declared in the class type and all the instance variables declared in each superclass of the class type, including all the instance variables that may be hidden. If there is not sufficient space available to allocate memory for the object, then creation of the class instance completes abruptly with an OutOfMemoryError. Otherwise, all the instance variables in the new object, including those declared in superclasses, are initialized to their default values .
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:
1. Assign the arguments for the constructor to newly created parameter variables for this constructor invocation.
2. If this constructor begins with an explicit constructor invocation 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.
3. 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 a 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.
4. Execute the instance variable initializers for this class, assigning their values 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. (In some early Java implementations, the compiler incorrectly omitted the code to initialize a field if the field initializer expression was a constant expression whose value was equal to the default initialization value for its type. This was a bug.)
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.
Finalization of Class Instances
The class Object has a protected method called finalize; this method can be overridden by other classes. The particular definition of finalize that can be invoked for an object is called the finalizer of that object. Before the storage for an object is reclaimed by the garbage collector, the Java Virtual Machine will invoke the finalizer of that object.
Finalizers provide a chance to free up resources (such as file descriptors or operating system graphics contexts) that cannot be freed automatically by an automatic storage manager. In such situations, simply reclaiming the memory used by an object would not guarantee that the resources it held would be reclaimed.
The Java language does not specify how soon a finalizer will be invoked, except to say that it will happen before the storage for the object is reused. Also, the Java language does not specify which thread will invoke the finalizer for any given object. If an uncaught exception is thrown during the finalization, the exception is ignored and finalization of that object terminates.
Finalization and Unloading of Classes and Interfaces
A Java Virtual Machine may provide mechanisms whereby classes are finalized and unloaded.2 The details of such mechanisms are not specified in the current version of The Java Language Specification. In general, groups of related class and interface types will be unloaded together. This can be used, for example, to unload a group of related types that have been loaded using a particular class loader. Such a group might consist of all the classes implementing a single applet in a Java-based browser such as HotJava, for example.
A class may not be unloaded while any instance of it is still reachable. A class or interface may not be unloaded while the Class object that represents it is still reachable.
If a class declares a class method classFinalize that takes no arguments, and returns no result:
static void classFinalize() { . . . }
then this method will be invoked before the class is unloaded. Like the finalize method for objects, this method will be automatically invoked only once. This method may optionally be declared private, protected, or public.
Note :
1)Note that a local variable is not initialized on its creation, and is only considered to hold a value once it is assigned to (§2.5.1).
2 Class finalization and unloading are not implemented as of Sun's JDK release 1.0.2.
3 The method runFinalizersOnExit is not implemented in Sun's JDK release 1.0.2.
Virtual Machine Exit
A Java Virtual Machine terminates all its activity and exits when one of two things happens:
• All the threads that are not daemon threads terminate.
• Some thread invokes the exit method of class Runtime or class System and the exit operation is permitted by the security manager.
A Java program can specify that the finalizers of all objects that have finalizers that have not been automatically invoked are to be run before the virtual machine exits. This is done by invoking the method runFinalizersOnExit of the class System with the argument true.3 The default is to not run finalizers on exit, and this behavior may be restored by invoking runFinalizersOnExit with the argument false. An invocation of the runFinalizersOnExit method is permitted only if the caller is allowed to exit, and is otherwise rejected by the security manager.
This section specifies activities that occur during execution of a Java program.
It specifies the detailed procedures used in starting up the virtual machine, class and interface type loading, linking, and initialization. It then specifies the procedures for creation of new class instances. It concludes by describing the unloading of classes and the procedure followed when a virtual machine exits.
Virtual Machine Start-upA Java Virtual Machine starts execution by invoking the method main of some specified class, passing it a single argument, which is an array of strings.
This causes the specified class to be loaded, linked to other types that it uses, and initialized.
The method main must be declared public, static, and void.
In Sun's JDK implementation on UNIX, the command line
Java Robo Shakanr Rajani Aishwarya Sun
will start a Java Virtual Machine by invoking the method main of class Robo (a class in an unnamed package), passing it an array containing the four strings "Shankar", "Rajani", "Aishwarya", and "Sun".
We now outline the steps the virtual machine may take to execute Robo, as an example of the loading, linking, and initialization processes that are described further in later sections.
The initial attempt to execute the method main of class Robo discovers that the class Robo is not loaded-that is, the virtual machine does not currently contain a binary representation for this class. The virtual machine then uses a ClassLoader to attempt to find such a binary representation. If this process fails, an error is thrown.
Loading:
Loading refers to the process of finding the binary form of a class or interface type with a particular name, perhaps by computing it on the fly, but more typically by retrieving a binary representation previously computed from source code by a compiler and constructing, from that binary form, a Class object to represent the class or interface. The binary format of a class or interface is normally the class file format
If an error occurs during class loading, then an instance of one of the following subclasses of class LinkageError will be thrown at any point in the Java program that (directly or indirectly) uses the type:
• ClassCircularityError: A class or interface could not be loaded because it would be its own superclass or superinterface ..
• ClassFormatError: The binary data that purports to specify a requested compiled class or interface is malformed.
• NoClassDefFoundError: No definition for a requested class or interface could be found by the relevant class loader.
Linking: Verification, Preparation, and Resolution
Linking is the process of taking a binary form of a class or interface type and combining it into the runtime state of the Java Virtual Machine, so that it can be executed. A class or interface type is always loaded before it is linked. Three different activities are involved in linking: verification, preparation, and resolution of symbolic references.
Java allows an implementation flexibility as to when linking activities (and, because of recursion, loading) take place, provided that the semantics of the language are respected, that a class or interface is completely verified and prepared before it is initialized, and that errors detected during linkage are thrown at a point in the program where some action is taken by the program that might require linkage to the class or interface involved in the error.
Verification ensures that the binary representation of a class or interface is structurally correct. For example, it checks that every instruction has a valid operation code; that every branch instruction branches to the start of some other instruction, rather than into the middle of an instruction; that every method is provided with a structurally correct signature; and that every instruction obeys the type discipline of the Java language.
If an error occurs during verification, then an instance of the following subclass of class LinkageError will be thrown at the point in the Java program that caused the class to be verified:
• VerifyError: The binary definition for a class or interface failed to pass a set of required checks to verify that it obeys the semantics of the Java language and that it cannot violate the integrity of the Java Virtual Machine.
Preparation involves creating the static fields for a class or interface and initializing such fields to the standard default values . This does not require the execution of any Java code; explicit initializers for static fields are executed as part of initialization , not preparation.
Java implementations must detect the following error during preparation:
• AbstractMethodError: A class that is not declared to be abstract has an abstract method. This can occur, for example, if a method that is originally not abstract is changed to be abstract after another class that inherits the now-abstract method declaration has been compiled.
A Java binary file references other classes and interfaces and their fields, methods, and constructors symbolically, using the fully qualified names of the other classes and interfaces. For fields and methods these symbolic references include the name of the class or interface type which declares the field or method, as well as the name of the field or method itself, together with appropriate type information.
Before a symbolic reference can be used it must undergo resolution, wherein a symbolic reference is checked to be correct and, typically, replaced with a direct reference that can be more efficiently processed if the reference is used repeatedly.
If an error occurs during resolution, then an instance of one of the following subclasses of class IncompatibleClassChangeError, or of some other subclass, or of IncompatibleClassChangeError itself (which is a subclass of the class Linkage-Error) may be thrown at any point in the Java program that uses a symbolic reference to the type:
• IllegalAccessError: A symbolic reference has been encountered that specifies a use or assignment of a field, or invocation of a method, or creation of an instance of a class, to which the code containing the reference does not have access because the field or method was declared private,protected, or default access (not public), or because the class was not declared public. This can occur, for example, if a field that is originally declared public is changed to be private after another class that refers to the field has been compiled.
• InstantiationError: A symbolic reference has been encountered that is used in a class instance creation expression, but an instance cannot be created because the reference turns out to refer to an interface or to an abstract class. This can occur, for example, if a class that is originally notabstract is changed to be abstract after another class that refers to the class in question has been compiled.
• NoSuchFieldError: A symbolic reference has been encountered that refers to a specific field of a specific class or interface, but the class or interface does not declare a field of that name (it is specifically not sufficient for it simply to be an inherited field of that class or interface). This can occur, for example, if a field declaration was deleted from a class after another class that refers to the field was compiled.
• NoSuchMethodError: A symbolic reference has been encountered that refers to a specific method of a specific class or interface, but the class or interface does not declare a method of that name and signature (it is specifically not sufficient for it simply to be an inherited method of that class or interface). This can occur, for example, if a method declaration was deleted from a class after another class that refers to the method was compiled
Initialization
Initialization of a class consists of executing its static initializers and the initializers for static fields declared in the class. Initialization of an interface consists of executing the initializers for fields declared in the interface.
Before a class is initialized, its superclass must be initialized, but interfaces implemented by the class need not be initialized. Similarly, the superinterfaces of an interface need not be initialized before the interface is initialized
• Before a class is initialized its superclasses are initialized, if they have not previously been initialized.
• Initialization of an interface does not, of itself, require initialization of any of its superinterfaces.
Creation of New Class Instances
A new class instance is explicitly created when one of the following situations occurs:
• Evaluation of a class instance creation expression creates a new instance of the class whose name appears in the expression.
• Invocation of the newInstance method of class Class creates a new instance of the class represented by the Class object for which the method was invoked.
A new class instance may be implicitly created in the following situations:
• Loading of a class or interface that contains a String literal may create a new String object to represent that literal. This may not occur if the same String has previously been interned.
• Execution of a string concatenation operator that is not part of a constant expression sometimes creates a new String object to represent the result. String concatenation operators may also create temporary wrapper objects for a value of a primitive type .
Each of these situations identifies a particular constructor to be called with specified arguments (possibly none) as part of the class instance creation process.
Whenever a new class instance is created, memory space is allocated for it with room for all the instance variables declared in the class type and all the instance variables declared in each superclass of the class type, including all the instance variables that may be hidden. If there is not sufficient space available to allocate memory for the object, then creation of the class instance completes abruptly with an OutOfMemoryError. Otherwise, all the instance variables in the new object, including those declared in superclasses, are initialized to their default values .
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:
1. Assign the arguments for the constructor to newly created parameter variables for this constructor invocation.
2. If this constructor begins with an explicit constructor invocation 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.
3. 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 a 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.
4. Execute the instance variable initializers for this class, assigning their values 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. (In some early Java implementations, the compiler incorrectly omitted the code to initialize a field if the field initializer expression was a constant expression whose value was equal to the default initialization value for its type. This was a bug.)
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.
Finalization of Class Instances
The class Object has a protected method called finalize; this method can be overridden by other classes. The particular definition of finalize that can be invoked for an object is called the finalizer of that object. Before the storage for an object is reclaimed by the garbage collector, the Java Virtual Machine will invoke the finalizer of that object.
Finalizers provide a chance to free up resources (such as file descriptors or operating system graphics contexts) that cannot be freed automatically by an automatic storage manager. In such situations, simply reclaiming the memory used by an object would not guarantee that the resources it held would be reclaimed.
The Java language does not specify how soon a finalizer will be invoked, except to say that it will happen before the storage for the object is reused. Also, the Java language does not specify which thread will invoke the finalizer for any given object. If an uncaught exception is thrown during the finalization, the exception is ignored and finalization of that object terminates.
Finalization and Unloading of Classes and Interfaces
A Java Virtual Machine may provide mechanisms whereby classes are finalized and unloaded.2 The details of such mechanisms are not specified in the current version of The Java Language Specification. In general, groups of related class and interface types will be unloaded together. This can be used, for example, to unload a group of related types that have been loaded using a particular class loader. Such a group might consist of all the classes implementing a single applet in a Java-based browser such as HotJava, for example.
A class may not be unloaded while any instance of it is still reachable. A class or interface may not be unloaded while the Class object that represents it is still reachable.
If a class declares a class method classFinalize that takes no arguments, and returns no result:
static void classFinalize() { . . . }
then this method will be invoked before the class is unloaded. Like the finalize method for objects, this method will be automatically invoked only once. This method may optionally be declared private, protected, or public.
Note :
1)Note that a local variable is not initialized on its creation, and is only considered to hold a value once it is assigned to (§2.5.1).
2 Class finalization and unloading are not implemented as of Sun's JDK release 1.0.2.
3 The method runFinalizersOnExit is not implemented in Sun's JDK release 1.0.2.
Virtual Machine Exit
A Java Virtual Machine terminates all its activity and exits when one of two things happens:
• All the threads that are not daemon threads terminate.
• Some thread invokes the exit method of class Runtime or class System and the exit operation is permitted by the security manager.
A Java program can specify that the finalizers of all objects that have finalizers that have not been automatically invoked are to be run before the virtual machine exits. This is done by invoking the method runFinalizersOnExit of the class System with the argument true.3 The default is to not run finalizers on exit, and this behavior may be restored by invoking runFinalizersOnExit with the argument false. An invocation of the runFinalizersOnExit method is permitted only if the caller is allowed to exit, and is otherwise rejected by the security manager.
Comments
Post a Comment