Movatterモバイル変換


[0]ホーム

URL:


Contents |Prev |Next |IndexThe Java Virtual Machine Specification


CHAPTER 2

Java Programming Language Concepts


The Java virtual machine was designed to support the Java programming language.Some concepts and vocabulary from the Java programming language are thus useful when attempting to understand the virtual machine. This chapter gives an overview intended to support the specification of the Java virtual machine, but is not itself a part of that specification.

The content of this chapter has been condensed from the first edition ofThe Java Language Specification, by James Gosling, Bill Joy, and Guy Steele.1 Readers familiar with the Java programming language, but not withTheJava Language Specification, should at least skim this chapter for the terminology it introduces. Any discrepancies between this chapter andThe Java Language Specificationshould be resolved in favor ofThe Java Language Specification.

This chapter does not attempt to provide an introduction to the Java programming language. For such an introduction, seeThe Java Programming Language, Second Edition, by Ken Arnold and James Gosling.


2.1 Unicode

Programs written in the Java programming language supported by JDK release 1.1.7 and the Java 2 platform, v1.2 use the Unicode character encoding, version 2.1, as specified inThe Unicode Standard, Version 2.0, ISBN 0-201-48345-9, and the update information for Version 2.1 of the Unicode Standard available athttp://www.unicode.org. Programs written in the Java programming language used version2.0.14 of the Unicode Standard in JDK releases 1.1 through 1.1.6 and used version1.1.5 of the Unicode Standard in JDK release 1.0.

Except for comments, identifiers(§2.2), and the contents of character and string literals(§2.3), all input elements in a program written in the Java programming language are formed from onlyASCII characters. ASCII (ANSI X3.4) is the American Standard Code for Information Interchange. The first 128 characters of the Unicode character encoding are the ASCII characters.


2.2 Identifiers

Anidentifier is an unlimited-length sequence of Unicodeletters anddigits, the first of which must be a letter. Letters and digits may be drawn from the entire Unicode character set, which supports most writing scripts in use in the world today. This allows programmers to use identifiers in their programs that are written in their native languages.

The method(§2.10)Character.isJavaLetter returnstrue when passed a Unicode character that is considered to be a letter in an identifier. The methodCharacter.isJavaLetterOrDigit returnstrue when passed a Unicode character that is considered to be a letter or digit in an identifier.

Two identifiers are the same only if they have the same Unicode character for each letter or digit; identifiers that have the same external appearance may still be different. An identifier must not be the same as a boolean literal(§2.3), the null literal(§2.3), or a keyword in the Java programming language.


2.3 Literals

Aliteral is the source code representation of a value of a primitive type(§2.4.1), theString type(§2.4.8), or the null type(§2.4). String literals and, more generally, strings that are the values of constant expressions are "interned" so as to share unique instances, using the methodString.intern.

The null type has one value, the null reference, denoted by the literalnull. Theboolean type has two values, denoted by the literalstrue andfalse.


2.4 Types and Values

The Java programming language isstrongly typed, which means that every variable and every expression has a type that is known at compile time. Types limit the valuesthat a variable(§2.5) can hold or that an expression can produce, limit the operationssupported on those values, and determine the meaning of those operations. Strong typing helps detect errors at compile time.

The types of the Java programming language are divided into two categories:primitive types(§2.4.1) andreference types(§2.4.6). There is also a specialnull type, the type of the expressionnull, which has no name. The null reference is the only possible value of an expression of null type and can always be converted to any reference type. In practice, the programmer can ignore the null type and just pretend thatnull is a special literal that can be of any reference type.

Corresponding to the primitive types and reference types, there are two categories of data values that can be stored in variables, passed as arguments, returned by methods, and operated upon:primitive values(§2.4.1) andreference values(§2.4.6).

2.4.1 Primitive Types and Values

Aprimitive type is a type that is predefined by the Java programming language and named by a reserved keyword.Primitive values do not share state with other primitivevalues. A variable whose type is a primitive type always holds a primitive value of that type.2

The primitive types are theboolean type and thenumeric types. The numeric types are theintegral types and thefloating-point types.

The integral types arebyte,short,int, andlong, whose values are 8-bit, 16-bit, 32-bit, and 64-bit signed two's-complement integers, respectively, andchar, whose values are 16-bit unsigned integers representing Unicode characters(§2.1).

The floating-point types arefloat anddouble, which are conceptually associated with the 32-bit single-precision and 64-bit double-precision IEEE 754 values and operations as specified inIEEE Standard for Binary Floating-Point Arithmetic, ANSI/IEEE Standard 754-1985 (IEEE, New York).

Theboolean type has the truth valuestrue andfalse.

2.4.2 Operators on Integral Values

The Java programming language provides a number of operators that act on integral values, including numerical comparison, arithmetic operators, increment and decrement,bitwise logical and shift operators, and numeric cast(§2.6.9).

Operands of certain unary and binary operators are subject to numeric promotion(§2.6.10).

The built-in integer operators do not indicate (positive or negative) overflow in any way; they wrap around on overflow. The only integer operators that can throw an exception are the integer divide and integer remainder operators, which can throw anArithmeticException if the right-hand operand is zero.

Any value of any integral type may be cast to or from any numeric type. There are no casts between integral types and the typeboolean.

2.4.3 Floating-Point Types, Value Sets, and Values

The IEEE 754 standard includes not only positive and negative sign-magnitude numbers, but also positive and negative zeros, positive and negativeinfinities, and a specialNot-a-Numbervalue (hereafter abbreviated as "NaN"). The NaN value is used to represent the result of certain invalid operations such as dividing zero by zero.

Every implementation of the Java programming language is required to support two standard sets of floating-point values, called thefloat value set and thedouble value set. In addition, an implementation of the Java programming language may support either or both of two extended-exponent floating-point value sets, called the float-extended-exponent value set and the double-extended-exponent value set. These extended-exponent value sets may, under certain circumstances, be used instead of the standard value sets to represent the values of expressions of type float or double.

The finite nonzero values of any floating-point value set can all be expressed in the form s ·m· 2(e -N + 1), wheres is +1 or -1,m is a positive integer less than 2N, ande is an integer betweenEmin = - (2K - 1-2) andEmax = 2K - 1-1, inclusive, and whereN andK are parameters that depend on the value set. Some values can be represented in this form in more than one way; for example, supposing that a valuev in a value set might be represented in this form using certain values fors,m, ande, then if it happened thatm was even ande was less than 2K -1, one could halvem and increasee by 1 to produce a second representation for the same valuev. A representation in this form is callednormalized ifm 2N -1; otherwise the representation is said to bedenormalized. If a value in a value set cannot be represented in such a way thatm 2N -1, then the value is said to be adenormalized value, because it has no normalized representation.

The constraints on the parametersN andK (and on the derived parametersEmin andEmax) for the two required and two optional floating-point value sets are summarized inTable 2.1.

Parameterfloatfloat-extended-exponentdoubledouble-extended-exponent
N24245353
K8 1111 15
Emax+127 +1023+1023 +16383
Emin-126 -1022-1022 -16382


Where one or both extended-exponent value sets are supported by an implementation, then for each supported extended-exponent value set there is a specific implementation-dependent constantK, whose value is constrained byTable 2.1; this valueK in turn dictates the values forEmin andEmax.

Each of the four value sets includes not only the finite nonzero values that are ascribed to it above, but also the five values positive zero, negative zero, positive infinity, negative infinity, and NaN.

Note that the constraints inTable 2.1 are designed so that every element of the float value set is necessarily also an element of the float-extended-exponent value set, the double value set, and the double-extended-exponent value set. Likewise, each element of the double value set is necessarily also an element of the double-extended-exponent value set. Each extended-exponent value set has a larger range of exponent values than the corresponding standard value set, but does not have more precision.

The elements of the float value set are exactly the values that can be represented using the single floating-point format defined in the IEEE 754 standard, except that there is only one NaN value (IEEE 754 specifies 224 - 2 distinct NaN values). The elements of the double value set are exactly the values that can be represented using the double floating-point format defined in the IEEE 754 standard, except that there is only one NaN value (IEEE 754 specifies 253 - 2 distinct NaN values). Note, however, that the elements of the float-extended-exponent and double-extended-exponent value sets defined here donot correspond to the values that can be represented using IEEE 754 single extended and double extended formats, respectively.

The float, float-extended-exponent, double, and double-extended-exponent value sets are not types. It is always correct for an implementation of the Java programming language to use an element of the float value set to represent a value of type float; however, it may be permissible in certain regions of code for an implementation to use an element of the float-extended-exponent value set instead. Similarly, it is always correct for an implementation to use an element of the double value set to represent a value of type double; however, it may be permissible in certain regions of code for an implementation to use an element of the double-extended-exponent value set instead.

Except for NaN, floating-point values areordered; arranged from smallest to largest, they are negative infinity, negative finite nonzero values, positive and negative zero, positive finite nonzero values, and positive infinity.

On comparison, positive zero and negative zero are equal; thus the result of the expression 0.0 == -0.0 is true and the result of 0.0 > -0.0 is false. But other operations can distinguish positive and negative zero; for example, 1.0/0.0 has the value positive infinity, while the value of 1.0/-0.0 is negative infinity.

NaN isunordered, so the numerical comparison operators <, <=, >, and >= return false if either or both operands are NaN. The equality operator == returns false if either operand is NaN, and the inequality operator != returns true if either operand is NaN. In particular, x != x is true if and only if x is NaN, and (x<y) == !(x>=y) will be false if x or y is NaN.

Any value of a floating-point type may be cast to or from any numeric type. There are no casts between floating-point types and the type boolean.

2.4.4 Operators on Floating-Point Values

The Java programming language provides a number of operators that act on floating-pointvalues, including numerical comparison, arithmetic operators, increment and decrement, and numeric cast(§2.6.9).

If at least one of the operands to a binary operator is of floating-point type, then the operation is a floating-point operation, even if the other operand is integral. Operands of certain unary and binary operators are subject to numeric promotion(§2.6.10).

The values returned by operators on floating-point numbers are those specified by IEEE 754. In particular, the Java programming language requires support of IEEE 754denormalized floating-point numbers andgradual underflow, which make it easier to prove desirable properties of particular numerical algorithms.

The Java programming language requires that floating-point arithmetic behave as if every floating-point operator rounded its floating-point result to the result precision.Inexact results must be rounded to the representable value nearest to the infinitely precise result; if the two nearest representable values are equally near, the one having zero as its least significant bit is chosen. This is the IEEE 754 standard's default rounding mode known asround to nearest mode.

When converting a floating-point value to an integer,round towards zero mode is used(§2.6.3). Round towards zero mode acts as though the number were truncated, discarding the significand bits. Round towards zero mode chooses as its result the format's value closest to and no greater in magnitude than the infinitely precise result.

The floating-point operators of the Java programming language produce no exceptions(§2.16). An operation that overflows produces a signed infinity; an operation that underflows produces a denormalized value or a signed zero; and an operation that has no mathematically definite result produces NaN. All numeric operations (except for numeric comparison) with NaN as an operand produce NaN as a result.

Any value of any floating-point type may be cast(§2.6.9) to or from any numeric type. There are no casts between floating-point types and the typeboolean.

2.4.5 Operators onboolean Values

The boolean operators include relational operators and logical operators. Onlyboolean expressions can be used in control flow statements and as the first operand of the conditional operator?:. An integral valuex can be converted to a value of typeboolean, following the C language convention that any nonzero value istrue, by the expressionx!=0. An object referenceobj can be converted to a value of typeboolean, following the C language convention that any reference other thannull istrue, by the expressionobj!=null.

There are no casts between the typeboolean and any other type.

2.4.6 Reference Types, Objects, and Reference Values

There are three kinds of reference types: theclass types(§2.8), theinterface types(§2.13), and thearray types(§2.15). Anobject is a dynamically created class instance or an array. The reference values (often justreferences) arepointersto these objects and a special null reference, which refers to no object.

A class instance is explicitly created by aclass instance creation expression, or by invoking thenewInstance method of classClass. An array is explicitly created by anarray creation expression. An object is created in the heap and is garbage-collected after there are no more references to it. Objects cannot be reclaimed or freed by explicit language directives.

There may be many references to the same object. Most objects have state, stored in the fields of objects that are instances of classes or in the variables that are the components of an array object. If two variables contain references to the same object, the state of the object can be modified using one variable's reference to the object, and then the altered state can be observed through the other variable's reference.

Each object has an associatedlock (§2.19,§8.13) that is used bysynchronized methods and by thesynchronized statement to provide control over concurrent access to state by multiple threads (§2.19,§8.12).

Reference types form a hierarchy. Each class type is a subclass of another class type, except for the classObject(§2.4.7), which is the superclass(§2.8.3) of all other class and array types. All objects, including arrays, support the methods of classObject. String literals(§2.3) are references to instances of classString(§2.4.8).

2.4.7 The ClassObject

The standard classObject is the superclass(§2.8.3) of all other classes. A variable of typeObject can hold a reference to any object, whether it is an instance of a class or an array. All class and array types inherit the methods of classObject.

2.4.8 The ClassString

Instances of classString represent sequences of Unicode characters(§2.1). AString object has a constant, unchanging value. String literals(§2.3) are references to instances of classString.

2.4.9 Operators on Objects

The operators on objects include field access, method invocation, cast, string concatenation,comparison for equality,instanceof, and the conditional operator?:.


2.5 Variables

Avariable is a storage location. It has an associated type, sometimes called itscompile-timetype, that is either a primitive type(§2.4.1) or a reference type(§2.4.6). A variable always contains a value that is assignment compatible(§2.6.7) with its type. A variable of a primitive type always holds a value of that exact primitive type. A variable of reference type can hold either a null reference or a reference to any object whose class is assignment compatible(§2.6.7) with the type of the variable.

Compatibility of the value of a variable with its type is guaranteed by the design of the language because default values(§2.5.1) are compatible and all assignments to a variable are checked, at compile time, for assignment compatibility. There are seven kinds of variables:

  1. Aclass variableis a field of a class type declared using the keywordstatic(§2.9.1) within a class declaration, or with or without the keywordstatic in an interface declaration. Class variables are created when the class or interface is loaded(§2.17.2) and are initialized on creation to default values(§2.5.1). The class variable effectively ceases to exist when its class or interface is unloaded(§2.17.8).

  2. Aninstance variable is a field declared within a class declaration without using the keywordstatic(§2.9.1). If a class T has a field a that is an instance variable, then a new instance variable a is created and initialized to a default value(§2.5.1) as part of each newly created object of class T or of any class that is a subclass of T. The instance variable effectively ceases to exist when the object of which it is a field is no longer referenced, after any necessary finalization of the object(§2.17.7) has been completed.

  3. Array components are unnamed variables that are created and initialized to default values(§2.5.1) whenever a new object that is an array is created(§2.17.6). The array components effectively cease to exist when the array is no longer referenced.

  4. Method parameters name argument values passed to a method. For every parameter declared in a method declaration, a new parameter variable is created each time that method is invoked. The new variable is initialized with the corresponding argument value from the method invocation. The method parameter effectively ceases to exist when the execution of the body of the method is complete.

  5. Constructor parameters name argument values passed to a constructor. For every parameter declared in a constructor declaration, a new parameter variable is created each time a class instance creation expression or explicit constructor invocation is evaluated. The new variable is initialized with the corresponding argument value from the creation expression or constructor invocation. The constructor parameter effectively ceases to exist when the execution of the body of the constructor is complete.

  6. Anexception-handler parameter variable is created each time an exception is caught by acatch clause of atry statement(§2.16.2). The new variable is initialized with the actual object associated with the exception(§2.16.3). The exception-handler parameter effectively ceases to exist when execution of the block associated with thecatch clause(§2.16.2) is complete.

  7. Local variablesare declared by local variable declaration statements. Whenever the flow of control enters a block or afor statement, a new variable is created for each local variable declared in a local variable declaration statement immediately contained within that block orfor statement. The local variable is not initialized, however, until the local variable declaration statement that declares it is executed. The local variable effectively ceases to exist when the execution of the block orfor statement is complete.

2.5.1 Initial Values of Variables

Every variable in a program must have a value before it is used:

2.5.2 Variables Have Types, Objects Have Classes

Every object belongs to some particular class. This is the class that was mentioned in the class instance creation expression that produced the object, or the class whose class object was used to invoke thenewInstance method to produce the object. This class is calledthe class of the object. An object is said to be aninstance of its class and of all superclasses of its class. Sometimes the class of an object is called its "runtime type," but "class" is the more accurate term.

(Sometimes a variable or expression is said to have a "runtime type," but that is an abuse of terminology; it refers to the class of the object referred to by the value of the variable or expression at run time, assuming that the value is notnull. Properly speaking, type is a compile-time notion. A variable or expression has a type; an object or array has no type, but belongs to a class.)

The type of a variable is always declared, and the type of an expression can be deduced at compile time. The type limits the possible values that the variable can hold or the expression can produce at run time. If a runtime value is a reference that is notnull, it refers to an object or array that has a class (not a type), and that class will necessarily be compatible with the compile-time type.

Even though a variable or expression may have a compile-time type that is an interface type, there are no instances of interfaces(§2.13). A variable or expression whose type is an interface type can reference any object whose class implements that interface.

Every array also has a class. The classes for arrays have strange names that are not valid identifiers; for example, the class for an array ofint components has the name"[I".


2.6 Conversions and Promotions

Aconversion from type S to type T allows an expression of type S to be treated at compile time as if it were of type T instead. In some cases this will require a correspondingaction at run time to check the validity of the conversion or to translate the runtime value of the expression into a form appropriate for the new type T.

Numeric promotions are conversions that change an operand of a numeric operation to a wider type, or both operands of a numeric operation to a common type, so that an operation can be performed.

In the Java programming language, there are six broad kinds of conversions:

There are fiveconversion contexts in which conversion expressions can occur. Each context allows conversions in some of the above-named categories but not others. The conversion contexts are:

String conversion only applies to operands of the binary+ and+= operators when one of the arguments is aString; it will not be covered further.

2.6.1 Identity Conversions

A conversion from a type to that same type is permitted for any type.

2.6.2 Widening Primitive Conversions

The following conversions on primitive types are called thewidening primitive conversions:

Widening conversions do not lose information about the sign or order of magnitude of a numeric value. Conversions widening from an integral type to another integral type do not lose any information at all; the numeric value is preserved exactly. Conversions widening fromfloat todouble instrictfp expressions(§2.18) also preserve the numeric value exactly; however, such conversions that are notstrictfp may lose information about the overall magnitude of the converted value.

Conversion of anint or along value tofloat, or of along value todouble, may lose precision, that is, the result may lose some of the least significant bits of the value; the resulting floating-point value is a correctly rounded version of the integer value, using IEEE 754 round to nearest mode(§2.4.4).

According to this rule, a widening conversion of a signed integer value to an integral type simply sign-extends the two's-complement representation of the integer value to fill the wider format. A widening conversion of a value of typechar to an integral type zero-extends the representation of the character value to fill the wider format.

Despite the fact that loss of precision may occur, widening conversions among primitive types never result in a runtime exception(§2.16).

2.6.3 Narrowing Primitive Conversions

The following conversions on primitive types are callednarrowing primitive conversions:

Narrowing conversions may lose information about the sign or order of magnitude, or both, of a numeric value (for example, narrowing anint value32763 to typebyte produces the value-5). Narrowing conversions may also lose precision.

A narrowing conversion of a signed integer to an integral type simply discards all but then lowest-order bits, wheren is the number of bits used to represent the type. This may cause the resulting value to have a different sign from the input value.

A narrowing conversion of a character to an integral type likewise simply discards all but then lowest bits, wheren is the number of bits used to represent the type. This may cause the resulting value to be a negative number, even though characters represent 16-bit unsigned integer values.

In a narrowing conversion of a floating-point number to an integral type, if the floating-point number is NaN, the result of the conversion is0 of the appropriate type. If the floating-point number is too large to be represented by the integral type or is positive infinity, the result is the largest representable value of the integral type. If the floating-point number is too small to be represented or is negative infinity, the result is the smallest representable value of the integral type. Otherwise, the result is the floating-point number rounded towards zero to an integer value using IEEE 754 round towards zero mode(§2.4.4)

A narrowing conversion fromdouble tofloat behaves in accordance with IEEE 754. The result is correctly rounded using IEEE 754 round to nearest mode(§2.4.4). A value too small to be represented as afloat is converted to a positive or negative zero; a value too large to be represented as afloat is converted to a positive or negative infinity. AdoubleNaN is always converted to afloatNaN.

Despite the fact that overflow, underflow, or loss of precision may occur, narrowing conversions among primitive types never result in a runtime exception.

2.6.4 Widening Reference Conversions

Widening reference conversions never require a special action at run time and thereforenever throw an exception at run time. Because they do not affect the Java virtual machine, they will not be considered further.

2.6.5 Narrowing Reference Conversions

The following permitted conversions are called thenarrowing reference conversions:

Such conversions require a test at run time to find out whether the actual reference value is a legitimate value of the new type. If it is not, the Java virtual machine throws aClassCastException.

2.6.6 Value Set Conversion

Value set conversion is the process of mapping a floating-point value from one value set(§2.4.3) to another without changing its type.

For each operation in an expression that is not FP-strict(§2.18), value set conversion allows an implementation of the Java programming language to choose between two options:

Within an FP-strict expression, value set conversion does not provide any choices; every implementation must behave in the same way:

Within an FP-strict expression, mapping values from the float-extended-exponent value set or double-extended-exponent value set is necessary only when a method is called whose declaration is not FP-strict and the implementation has chosen to represent the result of the method call as an element of an extended-exponent value set.

Whether in FP-strict code or code that is not FP-strict, value set conversion always leaves unchanged any value whose type is neither float nor double.

2.6.7 Assignment Conversion

Assignment conversion occurs when the value of an expression is assigned to a variable:the type of the expression must be converted to the type of the variable. Assignment contexts allow the use of an identity conversion(§2.6.1), a widening primitive conversion(§2.6.2), or a widening reference conversion(§2.6.4). In addition,a narrowing primitive conversion(§2.6.3) may be used if all of the following conditions are satisfied:

If the type of the expression can be converted to the type of a variable by assignment conversion, we say the expression (or its value) isassignable to the variable or, equivalently, that the type of the expression isassignment compatible with the type of the variable.

If the type of the variable isfloat ordouble, then value set conversion(§2.6.6) is applied after the type conversion:

An assignment conversion never causes an exception. A value of primitive type must not be assigned to a variable of reference type. A value of reference type must not be assigned to a variable of primitive type. A value of typeboolean can be assigned only to a variable of typeboolean. A value of the null type may be assigned to a variable of any reference type.

Assignment of a value of compile-time reference type S (source) to a variable of compile-time reference type T (target) is permitted:

2.6.8 Method Invocation Conversion

Method invocation conversion is applied to each argument value in a method or constructorinvocation: the type of the argument expression must be converted to the type of the corresponding parameter. Method invocation contexts allow the use of an identity conversion(§2.6.1), a widening primitive conversion(§2.6.2), or a wideningreference conversion(§2.6.4). Method invocation conversions specifically do not include the implicit narrowing of integer constants that is part of assignment conversion(§2.6.7).

If the type of an argument expression is either float or double, then value set conversion(§2.6.6) is applied after the type conversion:

2.6.9 Casting Conversion

Casting conversionsare more powerful than assignment or method invocation conversionsapplied to the operand of a cast operator: the type of the operand expression must be converted to the type explicitly named by the cast operator. Casting contexts allow the use of an identity conversion(§2.6.1), a widening primitive conversion(§2.6.2), a narrowing primitive conversion(§2.6.3), a widening reference conversion(§2.6.4), or a narrowing reference conversion(§2.6.5). Thus, casting conversionsare more inclusive than assignment or method invocation conversions: a cast can do any permitted conversion other than a string conversion.

Value set conversion(§2.6.6) is applied after the type conversion.

Casting can convert a value of any numeric type to any other numeric type. A value of typeboolean cannot be cast to another type. A value of reference type cannot be cast to a value of primitive type.

Some casts can be proven incorrect at compile time and result in a compile-time error. Otherwise, either the cast can be proven correct at compile time, or a runtime validity check is required. (SeeThe Java Language Specification for details.) If the value at run time is a null reference, then the cast is allowed. If the check at run time fails, aClassCastException is thrown.

2.6.10 Numeric Promotion

Numeric promotionis applied to the operands of an arithmetic operator. Numeric promotion contexts allow the use of an identity conversion(§2.6.1) or a widening primitive conversion(§2.6.2).

Numeric promotions are used to convert the operands of a numeric operator to a common type where an operation can be performed. The two kinds of numeric promotion areunary numeric promotion andbinary numeric promotion. The analogous conversions in C are called "the usual unary conversions" and "the usual binary conversions." Numeric promotion is not a general feature of the Java programming language, but rather a property of specific built-in operators.

An operator that applies unary numeric promotion to a single operand of numeric type converts an operand of typebyte,short, orchar toint by a widening primitive conversion, and otherwise leaves the operand alone. Value set conversion(§2.6.6) is then applied. The operands of the shift operators are promoted independently using unary numeric promotions.

When an operator applies binary numeric promotion to a pair of numeric operands, the following rules apply, in order, using widening primitive conversion to convert operands as necessary:

After type conversion, if any, value set conversion is applied to each operand.


2.7 Names and Packages

Names are used to refer to entities declared in a program. A declared entity is a package, type, member (field or method) of a type, parameter, or local variable. Programsare organized sets ofpackages.

2.7.1 Simple Names and Qualified Names

Asimple name is a single identifier(§2.2).Qualified names(§2.7.4) provide access to members of packages and reference types. Aqualified name consists of a name, a "." token, and an identifier.

Not all identifiers are part of a name. Identifiers are also used in declarations, where the identifier determines the name by which an entity will be known, in field access expressions and method invocation expressions, and in statement labels andbreak andcontinue statements that refer to statement labels.

2.7.2 Packages

A package consists of a number of compilation units and has a hierarchical name. Packages are independently developed, and each package has its own set of names, which helps to prevent name conflicts. Each Java virtual machine implementation determines how packages, compilation units, and subpackages are created and stored; which top-level package names are in scope in a particular compilation; and which packages are accessible. Packages may be stored in a local file system, in a distributed file system, or in some form of database.

A package name component or class name might contain a character that cannot legally appear in a host file system's ordinary directory or file name: for instance, a Unicode character on a system that allows only ASCII characters in file names.

A Java virtual machine implementation must support at least one unnamed package; it may support more than one but is not required to do so. Which compilation units are in each unnamed package is determined by the host system. Unnamed packages are provided principally for convenience when developing small or temporary applications or when just beginning development.

Animport declaration allows a type declared in another package to be known by a simple name rather than by the fully qualified name(§2.7.5) of the type. An import declaration affects only the type declarations of a single compilation unit. A compilation unit automatically imports each of thepublic type names declared in the predefined packagejava.lang.

2.7.3 Members

Packages and reference types havemembers. The members of a package(§2.7.2) are subpackages and all the class(§2.8) and interface(§2.13) types declared in all the compilation units of the package. The members of a reference type are fields(§2.9), methods(§2.10), and nested classes and interfaces.

2.7.3.1 The Members of a Package

In general, the subpackages of a package are determined by the host system. However,the standard packagejava always has the subpackageslang,util,io, andnet. No two distinct members of the same package may have the same simple name(§2.7.1), but members of different packages may have the same simple name.

2.7.3.2 The Members of a Class Type

The members of a class type(§2.8) are fields(§2.9), methods(§2.10), and nested classes and interfaces. These include members inherited from its direct superclass(§2.8.3), if it has one, members inherited from any direct superinterfaces(§2.13.2), and any members declared in the body of the class. There is no restriction against a field and a method of a class type having the same simple name.

A class type may have two or more methods with the same simple name if they have different numbers of parameters or different parameter types in at least one parameter position. Such a method member name is said to beoverloaded. A class type may contain a declaration for a method with the same name and the same signature as a method that would otherwise be inherited from a superclass or superinterface. In this case, the method of the superclass or superinterface is not inherited. If the method not inherited isabstract, the new declaration is said toimplement the method; if it is notabstract, the new declaration is said tooverride it.

2.7.3.3 The Members of an Interface Type

The members of an interface type(§2.13) are fields, methods, and nested classes and interfaces. The members of an interface are the members inherited from any direct superinterfaces(§2.13.2) and members declared in the body of the interface.

2.7.3.4 The Members of an Array Type

The members of an array type(§2.15) are the members inherited from its superclass, the classObject(§2.4.7), and the fieldlength, which is a constant (final) field of every array.

2.7.4 Qualified Names and Access Control

Qualified names(§2.7.1) are a means of access to members of packages and referencetypes; related means of access include field access expressions and method invocation expressions. All three are syntactically similar in that a "." token appears, preceded by some indication of a package, type, or expression having a type and followedby an identifier that names a member of the package or type. These are collectivelyknown as constructs forqualified access.

The Java programming language provides mechanisms for limiting qualified access, to prevent users of a package or class from depending on unnecessary details of the implementation of that package or class. Access control also applies to constructors.

Whether a package is accessible is determined by the host system.

A class or interface may be declaredpublic, in which case it may be accessed, using a qualified name, by any class or interface that can access the package in which it is declared. A class or interface that is not declaredpublic may be accessed from, and only from, anywhere in the package in which it is declared.

Every field or method of an interface must bepublic. Every member of apublic interface is implicitlypublic, whether or not the keywordpublic appears in its declaration. It follows that a member of an interface is accessible if and only if the interface itself is accessible.

A field, method, or constructor of a class may be declared using at most one of thepublic,private, orprotected keywords. Apublic member may be accessed by any class or interface. Aprivate member may be accessed only from within the class that contains its declaration. A member that is not declaredpublic,protected, orprivate is said to havedefault access and may be accessed from, and only from, anywhere in the package in which it is declared.

Aprotected member of an object may be accessed only by code responsible for the implementation of that object. To be precise, aprotected member may be accessed from anywhere in the package in which it is declared and, in addition, it may be accessed from within any declaration of a subclass of the class type that contains its declaration, provided that certain restrictions are obeyed.

2.7.5 Fully Qualified Names

Every package, class, interface, array type, and primitive type has a fully qualified name. It follows that every type except the null type has a fully qualified name.


2.8 Classes

Aclass declarationspecifies a new reference type and provides its implementation. Each class is implemented as an extension or subclass of a single existing class. A class may also implement one or more interfaces.

The body of a class declares members (fields and methods), static initializers, and constructors.

2.8.1 Class Names

If a class is declared in a named package with the fully qualified name P, then the class has the fully qualified name P.Identifier. If the class is in an unnamed package, then the class has the fully qualified nameIdentifier.

Two classes are thesame class (and therefore thesame type) if they are loaded by the same class loader(§2.17.2) and they have the same fully qualified name(§2.7.5).

2.8.2 Class Modifiers

A class declaration may includeclass modifiers. A class may be declaredpublic, as discussed in§2.7.4.

Anabstract class is a class that is incomplete, or considered incomplete. Onlyabstract classes may haveabstract methods(§2.10.3), that is, methods that are declared but not yet implemented.

A class can be declaredfinal if its definition is complete and no subclasses are desired or required. Because afinal class never has any subclasses, the methods of afinal class cannot be overridden in a subclass. A class cannot be bothfinal andabstract, because the implementation of such a class could never be completed.

A class can be declaredstrictfp to indicate that all expressions in the methods of the class are FP-strict(§2.18), whether or not the methods themselves are declared FP-strict.

A class is declaredpublic to make its type available to packages other than the one in which it is declared. Apublic class is accessible from other packages, using either its fully qualified name or a shorter name created by animport declaration(§2.7.2), whenever the host permits access to its package. If a class lacks thepublic modifier, access to the class declaration is limited to the package in which it is declared.

2.8.3 Superclasses and Subclasses

The optionalextends clause in a class declaration specifies thedirect superclass of the current class, the class from whose implementation the implementation of the current class is derived. A class is said to be adirect subclass of the class itextends. Only the classObject(§2.4.7) has no direct superclass. If theextends clause is omitted from a class declaration, then the superclass of the new class isObject.

Thesubclass relationship is the transitive closure of the direct subclass relationship. A class A is a subclass of a class C if A is a direct subclass of C, or if there is a direct subclass B of C and class A is a subclass of B. Class A is said to be asuperclass of class C whenever C is a subclass of A.

2.8.4 The Class Members

The members of a class type include all of the following:

Members of a superclass that are declaredprivate are not inherited by subclasses of that class. Members of a class that are not declaredprivate,protected, orpublic are not inherited by subclasses declared in a package other than the one in which the class is declared. Constructors(§2.12) and static initializers(§2.11) are not members and therefore are not inherited.


2.9 Fields

The variables of a class type are itsfields. Class (static) variables exist once per class. Instance variables exist once per instance of the class. Fields may include initializersand may be modified using various modifier keywords.

If the class declares a field with a certain name, then the declaration of that field is said tohide any and all accessible declarations of fields with the same name in the superclasses and superinterfaces of the class. A class inherits from its direct superclass and direct superinterfaces all the fields of the superclass and superinterfaces that are accessible to code in the class and are not hidden by a declaration in the class. A hidden field can be accessed by using a qualified name (if it isstatic) or by using a field access expression that contains a cast to a superclass type or the keywordsuper.

A value stored in a field of type float is always an element of the float value set(§2.4.3); similarly, a value stored in a field of type double is always an element of the double value set. It is not permitted for a field of type float to contain an element of the float-extended-exponent value set that is not also an element of the float value set, nor for a field of type double to contain an element of the double-extended-exponent value set that is not also an element of the double value set.

2.9.1 Field Modifiers

Fields may be declaredpublic,protected, orprivate, as discussed in§2.7.4.

If a field is declaredstatic, there exists exactly one incarnation of the field, no matter how many instances (possibly zero) of the class may eventually be created. Astatic field, sometimes called aclass variable, is incarnated when the class is initialized(§2.17.4).

A field that is not declaredstatic is called aninstance variable. Whenever a new instance of a class is created, a new variable associated with that instance is created for every instance variable declared in that class or in any of its superclasses.

A field can be declaredfinal, in which case its declarator must include a variable initializer(§2.9.2). Both class and instance variables (static and non-static fields) may be declaredfinal. Once afinal field has been initialized, it always contains the same value. If afinal field holds a reference to an object, then the state of the object may be changed by operations on the object, but the field will always refer to the same object.

Variables may be markedtransient to indicate that they are not part of the persistent state of an object. Thetransient attribute can be used by an implementation to support special system services.The Java Language Specification does not yet specify details of such services.

The Java programming language allows threads that access shared variables to keep private working copies of the variables; this allows a more efficient implementation of multiple threads(§2.19). These working copies need to be reconciled with the master copies in the shared main memory only at prescribed synchronization points, namely, when objects are locked or unlocked(§2.19). As a rule, to make sure that shared variables are consistently and reliably updated, a thread should ensure that it has exclusive access to such variables by obtaining a lock that conventionally enforces mutual exclusion for those shared variables.

Alternatively, a field may be declaredvolatile, in which case a thread must reconcile its working copy of the field with the master copy every time it accesses the variable. Moreover, operations on the master copies of one or more volatile variables on behalf of a thread are performed by the main memory in exactly the order that the thread requested. Afinal field cannot also be declaredvolatile.

2.9.2 Initialization of Fields

If a field declaration contains a variable initializer, then it has the semantics of an assignment to the declared variable, and:


2.10 Methods

Amethoddeclares executable code that can be invoked, passing a fixed number of values as arguments. Every method declaration belongs to some class. A class inheritsfrom its direct superclass(§2.8.3) and any direct superinterfaces(§2.13.2) all the accessible methods of the superclass and superinterfaces, with one exception: if a name is declared as a method in the new class, then no method with the same signature(§2.10.2) is inherited. Instead, the newly declared method is said tooverride any such method declaration. An overriding method must not conflict with the definitionthat it overrides, for instance, by having a different return type. Overridden methods of the superclass can be accessed using a method invocation expression involving thesuper keyword.

2.10.1 Formal Parameters

Theformal parameters of a method, if any, are specified by a list of comma-separatedparameter specifiers. Each parameter specifier consists of a type and an identifierthat specifies the name of the parameter. When the method is invoked, the values of the actual argument expressions initialize newly created parameter variables(§2.5), each of the declared type, before execution of the body of the method.

A method parameter of type float always contains an element of the float value set(§2.4.3); similarly, a method parameter of type double always contains an element of the double value set. It is not permitted for a method parameter of type float to contain an element of the float-extended-exponent value set that is not also an element of the float value set, nor for a method parameter of type double to contain an element of the double-extended-exponent value set that is not also an element of the double value set.

Where an actual argument expression corresponding to a parameter variable is not FP-strict(§2.18), evaluation of that actual argument expression is permitted to use values drawn from the appropriate extended-exponent value sets. Prior to being stored in the parameter variable, the result of such an expression is mapped to the nearest value in the corresponding standard value set by method invocation conversion(§2.6.8).

2.10.2 Method Signature

Thesignature of a method consists of the name of the method and the number and type of formal parameters(§2.10.1) of the method. A class may not declare two methods with the same signature.

2.10.3 Method Modifiers

The access modifierspublic,protected, andprivate are discussed inSection 2.7.4.

Anabstract method declaration introduces the method as a member, providing its signature(§2.10.2), return type, andthrows clause (if any), but does not provide an implementation. The declaration of anabstract method m must appear within anabstract class (call it A). Every subclass of A that is not itselfabstract must provide an implementation for m. A method declaredabstract cannot also be declared to beprivate,static,final,native,strictfp, orsynchronized.

A method that is declaredstatic is called aclass method. A class method is always invoked without reference to a particular object. A class method may refer to other fields and methods of the class by simple name only if they are class methods and class (static) variables.

A method that is not declaredstatic is aninstance method. An instance method is always invoked with respect to an object, which becomes the current object to which the keywordsthis andsuper refer during execution of the method body.

A method can be declaredfinal to prevent subclasses from overriding or hiding it. Aprivate method and all methods declared in afinal class(§2.8.2) are implicitlyfinal, because it is impossible to override them. If a method isfinal or implicitlyfinal, a compiler or a runtime code generator can safely "inline" the body of afinal method, replacing an invocation of the method with the code in its body.

Asynchronized method will acquire a monitor lock(§2.19) before it executes. For a class (static) method, the lock associated with the class object for the method's class is used. For an instance method, the lock associated withthis (the object for which the method is invoked) is used. The same per-object lock is used by thesynchronized statement.

A method can be declaredstrictfp to indicate that all expressions in the method are FP-strict(§2.18).

A method can be declarednative to indicate that it is implemented in platform-dependent code, typically written in another programming language such as C, C++, or assembly language. A method may not be declared to be bothnative andstrictfp.


2.11 Static Initializers

Anystatic initializers declared in a class are executed when the class is initialized(§2.17.4) and, together with any field initializers(§2.9.2) for class variables, may be used to initialize the class variables of the class(§2.17.4).

The static initializers and class variable initializers are executed in textual order. They may not refer to class variables declared in the class whose declarations appear textually after the use, even though these class variables are in scope. This restriction is designed to catch, at compile time, most circular or otherwise malformed initializations.


2.12 Constructors

Aconstructor is used in the creation of an object that is an instance of a class. The constructor declaration looks like a method declaration that has no result type. Constructorsare invoked by class instance creation expressions(§2.17.6), by the conversionsand concatenations caused by the string concatenation operator+, and by explicit constructor invocations from other constructors; they are never invoked by method invocation expressions.

Constructor declarations are not members. They are never inherited and therefore are not subject to hiding or overriding.

If a constructor body does not begin with an explicit constructor invocation and the constructor being declared is not part of the primordial classObject, then the constructor body is implicitly assumed by the compiler to begin with a superclass constructor invocation "super();", an invocation of the constructor of the direct superclass that takes no arguments.

If a class declares no constructors then adefault constructor, which takes no arguments, is automatically provided. If the class being declared isObject, then the default constructor has an empty body. Otherwise, the default constructor takes no arguments and simply invokes the superclass constructor with no arguments. If the class is declaredpublic, then the default constructor is implicitly given the access modifierpublic. Otherwise, the default constructor has the default access implied by no access modifier(§2.7.4).

A class can be designed to prevent code outside the class declaration from creating instances of the class by declaring at least one constructor, in order to prevent the creation of an implicit constructor, and declaring all constructors to beprivate.

2.12.1 Constructor Modifiers

Access to constructors is governed by the access modifierspublic,protected, andprivate(§2.7.4).

A constructor cannot beabstract,static,final,native, orsynchronized. A constructor cannot be declared to bestrictfp. This difference in the definitions for method modifiers(§2.10.3) and constructor modifiers is an intentional language design choice; it effectively ensures that a constructor is FP-strict(§2.18) if and only if its class is FP-strict, so to speak.


2.13 Interfaces

Aninterface is a reference type whose members are constants andabstract methods.This type has no implementation, but otherwise unrelated classes can implementit by providing implementations for itsabstract methods. Programs can use interfaces to make it unnecessary for related classes to share a commonabstract superclass or to add methods toObject.

An interface may be declared to be adirect extensionof one or more other interfaces, meaning that it implicitly specifies all theabstract methods and constants of the interfaces it extends, except for any constants that it may hide, and perhaps adds newly declared members of its own.

A class may be declared todirectly implement one or more interfaces, meaning that any instance of the class implements all theabstract methods specified by that interface. A class necessarily implements all the interfaces that its direct superclasses and direct superinterfaces do. This (multiple) interface inheritance allows objects to support (multiple) common behaviors without sharing any implementation.

A variable whose declared type is an interface type may have as its value a reference to an object that is an instance of any class that is declared to implement the specified interface. It is not sufficient that the class happens to implement all theabstract methods of the interface; the class or one of its superclasses must actually be declared to implement the interface, or else the class is not considered to implement the interface.

2.13.1 Interface Modifiers

An interface declaration may be preceded by the interface modifierspublic,strictfp, andabstract. The access modifierpublic is discussed in(§2.7.4). Every interface is implicitlyabstract. All members of interfaces are implicitlypublic.

An interface cannot befinal, because the implementation of such a class could never be completed.

2.13.2 Superinterfaces

If anextends clause is provided, then the interface being declared extends each of the other named interfaces and therefore inherits the methods and constants of each of the other named interfaces. Any class thatimplements the declared interface is also considered to implement all the interfaces that this interface extends and that are accessible to the class.

Theimplements clause in a class declaration lists the names of interfaces that aredirect superinterfaces of the class being declared. All interfaces in the current package are accessible. Interfaces in other packages are accessible if the host system permits access to the package and the interface is declaredpublic.

An interface type K is asuperinterface of class type C if K is a direct superinterface of C ; or if C has a direct superinterface J that has K as a superinterface; or if K is a superinterface of the direct superclass of C. A class is said toimplement all its superinterfaces.

There is no analogue of the classObject for interfaces; that is, while every class is an extension of classObject, there is no single interface of which all interfaces are extensions.

2.13.3 Interface Members

The members of an interface are those members inherited from direct superinterfacesand those members declared in the interface. The interface inherits, from the interfaces it extends, all members of those interfaces, except for fields with the same names as fields it declares. Interface members are either fields or methods.

2.13.3.1 Interface (Constant) Fields

Every field declaration in the body of an interface is implicitlystatic andfinal. Interfaces do not have instance variables. Every field declaration in an interface is itself implicitlypublic. A constant declaration in an interface must not include either of the modifierstransient orvolatile.

Every field in the body of an interface must have an initialization expression, which need not be a constant expression. The variable initializer is evaluated and the assignment performed exactly once, when the interface is initialized(§2.17.4).

2.13.3.2 Interface (Abstract) Methods

Every method declaration in the body of an interface is implicitlyabstract and implicitlypublic.

A method declared in the body of an interface must not be declaredstatic, becausestatic methods cannot beabstract.

A method declared in the body of an interface must not be declarednative,strictfp, orsynchronized, because those keywords describe implementation properties rather than interface properties; however, a method declared in an interface may be implemented by a method that is declarednative,strictfp, orsynchronized in a class that implements the interface. A method declared in the body of an interface must not be declaredfinal; however, one may be implemented by a method that is declaredfinal in a class that implements the interface.

2.13.4 Overriding, Inheritance, and Overloading in Interfaces

If the interface declares a method, then the declaration of that method is said tooverride any and all methods with the same signature in the superinterfaces of the interface that would otherwise be accessible to code in this interface.

An interface inherits from its direct superinterfaces all methods of the superinterfaces that are not overridden by a method declared in the interface.

If two methods of an interface (whether both are declared in the same interface, or both are inherited by an interface, or one is declared and one is inherited) have the same name but different signatures, then the method name is said to beoverloaded.


2.14 Nested Classes and Interfaces

JDK release 1.1 addednested classes and interfaces to the Java programming language. Nested classes and interfaces are sometimes referred to asinner classes and interfaces, which are one sort of nested classes and interfaces. However, nested classes and interfaces also encompass nested top-level classes and interfaces, which are not inner classes or interfaces.

A full specification of nested classes and interfaces will be published in the second edition ofThe Java Language Specification. Until then, interested persons should refer to the Inner Classes Specification, which may be found athttp://java.sun.com/products/jdk/1.1/docs/guide/innerclasses/spec/innerclasses.doc.html.


2.15 Arrays

Arrays are objects, are dynamically created, and may be assigned to variables of typeObject(§2.4.7). All methods on arrays are inherited from classObject except theclone method, which arrays override. All arrays implement the interfacesCloneable andjava.io.Serializable.

An array object contains a number of variables. That number may be zero, in which case the array is said to beempty. The variables contained in an array have no names; instead they are referenced by array access expressions that use nonnegative integer index values. These variables are called thecomponents of the array. If an array hasn components, we sayn is thelength of the array.

An array of zero components is not the same as the null reference(§2.4).

An array component of type float is always an element of the float value set(§2.4.3); similarly, a component of type double is always an element of the double value set. A component of type float may not be an element of the float-extended-exponent value set unless it is also an element of the float value set. A component of type double may not be an element of the double-extended-exponent value set unless it is also an element of the double value set.

2.15.1 Array Types

All the components of an array have the same type, called thecomponent type of the array. If the component type of an array is T, then the type of the array itself is writtenT[].

The component type of an array may itself be an array type. The components of such an array may contain references to subarrays. If, starting from any array type, one considers its component type, and then (if that is also an array type) the component type of that type, and so on, eventually one must reach a component type that is not an array type; this is called theelement type of the original array, and the components at this level of the data structure are called theelements of the original array.

There are three situations in which an element of an array can be an array: if the element type is of typeObject(§2.4.7),Cloneable, orjava.io.Serializable, then some or all of the elements may be arrays, because every array object can be assigned to a variable of one of those types.

In the Java programming language, unlike in C, an array ofchar is not aString(§2.4.7), and neither aString nor an array ofchar is terminated by'\u0000' (theNUL-character). AString object is immutable (its value never changes), while an array ofchar has mutable elements.

The element type of an array may be any type, whether primitive or reference. In particular, arrays with an interface type as the component type are supported; the elements of such an array may have as their value a null reference or instances of any class type that implements the interface. Arrays with anabstract class type as the component type are supported; the elements of such an array may have as their value a null reference or instances of any subclass of thisabstract class that is not itselfabstract.

2.15.2 Array Variables

A variable of array type holds a reference to an object. Declaring a variable of array type does not create an array object or allocate any space for array components. It creates only the variable itself, which can contain a reference to an array.

Because an array's length is not part of its type, a single variable of array type may contain references to arrays of different lengths. Once an array object is created, its length never changes. To make an array variable refer to an array of different length, a reference to a different array must be assigned to the variable.

If an array variable v has type A[], where A is a reference type, then v can hold a reference to any array type B[], provided B can be assigned to A(§2.6.7).

2.15.3 Array Creation

An array is created by anarray creation expression or anarray initializer.

2.15.4 Array Access

A component of an array is accessed using anarray access expression. Arrays may be indexed byint values;short,byte, orchar values may also be used as they are subjected to unary numeric promotion(§2.6.10) and becomeint values.

All arrays are 0-origin. An array with lengthn can be indexed by the integers 0 throughn - 1. All array accesses are checked at run time; an attempt to use an index that is less than zero or greater than or equal to the length of the array causes anArrayIndexOutOfBoundsException to be thrown.


2.16 Exceptions

When a program violates the semantic constraints of the Java programming language,the Java virtual machine signals this error to the program as anexception. An example of such a violation is an attempt to index outside the bounds of an array. The Java programming language specifies that an exception will be thrown when semantic constraints are violated and will cause a nonlocal transfer of control from the point where the exception occurred to a point that can be specified by the programmer.An exception is said to bethrown from the point where it occurred and is said to becaught at the point to which control is transferred. A method invocation that completes because an exception causes transfer of control to a point outside the method is said tocomplete abruptly.

Programs can also throw exceptions explicitly, usingthrow statements. This provides an alternative to the old-fashioned style of handling error conditions by returning distinguished error values, such as the integer value-1, where a negative value would not normally be expected.

Every exception is represented by an instance of the classThrowable or one of its subclasses; such an object can be used to carry information from the point at which an exception occurs to the handler that catches it. Handlers are established bycatch clauses oftry statements. During the process of throwing an exception, the Java virtual machine abruptly completes, one by one, any expressions, statements, method and constructor invocations, static initializers, and field initialization expressions that have begun but not completed execution in the current thread. This process continues until a handler is found that indicates that it handles the thrown exception by naming the class of the exception or a superclass of the class of the exception. If no such handler is found, then the methoduncaughtException is invoked for theThreadGroup that is the parent of the current thread.

In the Java programming language the exception mechanism is integrated with the synchronization model(§2.19) so that locks are properly released assynchronized statements and so that invocations ofsynchronized methods complete abruptly.

The specific exceptions covered in this section are that subset of the predefined exceptions that can be thrown directly by the operation of the Java virtual machine. Additional exceptions can be thrown by class library or user code; these exceptions are not covered here. SeeThe Java Language Specification for information on all predefined exceptions.

2.16.1 The Causes of Exceptions

An exception is thrown for one of three reasons:

  1. An abnormal execution condition was synchronously detected by the Java virtual machine. These exceptions are not thrown at an arbitrary point in the program, but rather at a point where they are specified as a possible result of an expression evaluation or statement execution, such as:

  2. Athrow statement was executed.

  3. An asynchronous exception occurred because:

Exceptions are represented by instances of the classThrowable and instances of its subclasses. These classes are, collectively, theexception classes.

2.16.2 Handling an Exception

When an exception is thrown, control is transferred from the code that caused the exception to the nearest dynamically enclosingcatch clause of atry statement that handles the exception.

A statement or expression isdynamically enclosed by acatch clause if it appears within thetry block of thetry statement of which thecatch clause is a part, or if the caller of the statement or expression is dynamically enclosed by thecatch clause.

Thecaller of a statement or expression depends on where it occurs:

Whether a particularcatch clausehandles an exception is determined by comparing the class of the object that was thrown to the declared type of the parameter of thecatch clause. Thecatch clause handles the exception if the type of its parameter is the class of the exception or a superclass of the class of the exception. Equivalently, acatch clause will catch any exception object that is aninstanceof the declared parameter type.

The control transfer that occurs when an exception is thrown causes abrupt completion of expressions and statements until acatch clause is encountered that can handle the exception; execution then continues by executing the block of thatcatch clause. The code that caused the exception is never resumed.

If nocatch clause handling an exception can be found, then the current thread (the thread that encountered the exception) is terminated, but only after allfinally clauses have been executed and the methoduncaughtException has been invoked for theThreadGroup that is the parent of the current thread.

In situations where it is desirable to ensure that one block of code is always executed after another, even if that other block of code completes abruptly, atry statement with afinally clause may be used. If atry orcatch block in atry-finally ortry-catch-finally statement completes abruptly, then thefinally clause is executed during propagation of the exception, even if no matchingcatch clause is ultimately found. If afinally clause is executed because of abrupt completion of atry block and thefinally clause itself completes abruptly, then the reason for the abrupt completion of thetry block is discarded and the new reason for abrupt completion is propagated from there.

Most exceptions occur synchronously as a result of an action by the thread in which they occur and at a point in the program that is specified to possibly result in such an exception. An asynchronous exception is, by contrast, an exception that can potentially occur at any point in the execution of a program.

Asynchronous exceptions are rare. They occur only as a result of:

Astop method may be invoked by one thread to affect another thread or all the threads in a specified thread group. It is asynchronous because it may occur at any point in the execution of the other thread or threads. An internal error is considered asynchronous so that it may be handled using the same mechanism that handles thestop method, as will now be described.

The Java programming language permits a small but bounded amount of execution to occur before an asynchronous exception is thrown. This delay is permitted to allow optimized code to detect and throw these exceptions at points where it is practical to handle them while obeying the semantics of the language.

A simple implementation might poll for asynchronous exceptions at the point of each control transfer instruction. Since a program has a finite size, this provides a bound on the total delay in detecting an asynchronous exception. Since no asynchronous exception will occur between control transfers, the code generator has some flexibility to reorder computation between control transfers for greater performance.

All exceptions in the Java programming language areprecise: when the transfer of control takes place, all effects of the statements executed and expressions evaluated before the point from which the exception is thrown must appear to have taken place. No expressions, statements, or parts thereof that occur after the point from which the exception is thrown may appear to have been evaluated. If optimized code has speculatively executed some of the expressions or statements which follow the point at which the exception occurs, such code must be prepared to hide this speculative execution from the user-visible state of the program.

2.16.3 The Exception Hierarchy

The possible exceptions in a program are organized in a hierarchy of classes, rooted at classThrowable, a direct subclass ofObject. The classesException andError are direct subclasses ofThrowable. The classRuntimeException is a direct subclass ofException.

Programs can use the preexisting exception classes inthrow statements, or define additional exception classes as subclasses ofThrowable or of any of its subclasses, as appropriate. To take advantage of compile-time checking for exception handlers, it is typical to define most new exception classes as checked exception classes, specifically as subclasses ofException that are not subclasses ofRuntimeException.

2.16.4 The ClassesException andRuntimeException

The classException is the superclass of all the standard exceptions that ordinary programs may wish to recover from.

The classRuntimeException is a subclass of classException. The subclasses ofRuntimeException are unchecked exception classes. The packagejava.lang defines the following standard unchecked runtime exceptions:

The classError and its standard subclasses are exceptions from which ordinary programs are not ordinarily expected to recover. The classError is a separate subclass ofThrowable, distinct fromException in the class hierarchy, in order to allow programs to use the idiom

        } catch (Exception e) {
to catch all exceptions from which recovery may be possible without catching errors from which recovery is typically not possible. Packagejava.lang defines all the error classes described here.

The Java virtual machine throws an object that is an instance of a subclass ofLinkageError when a loading(§2.17.2), linking(§2.17.3), or initialization(§2.17.4) error occurs.

A Java virtual machine implementation throws an object that is an instance of a subclass of the classVirtualMachineError when an internal error or resource limitation prevents it from implementing the semantics of the Java programming language. This specification defines the following virtual machine errors:


2.17 Execution

This section specifies activities that occur during execution of a program. It is organizedaround the life cycle of the Java virtual machine and of the classes, interfaces, and objects that form a program. It specifies the detailed procedures used in starting up the virtual machine(§2.17.1), class and interface type loading(§2.17.2), linking(§2.17.3), and initialization(§2.17.4). It then specifies the procedures for creation of new class instances(§2.17.6). It concludes by describing the unloading of classes(§2.17.8) and the procedure followed when a virtual machine exits(§2.17.9).

2.17.1 Virtual Machine Start-up

The Java virtual machine starts execution by invoking the methodmain of some specified class and passing it a single argument, which is an array of strings. This causes the specified class to be loaded(§2.17.2), linked(§2.17.3) to other types that it uses, and initialized(§2.17.4). The methodmain must be declaredpublic,static, andvoid.

The manner in which the initial class is specified to the Java virtual machine is beyond the scope of this specification, but it is typical, in host environments that use command lines, for the fully qualified name of the class to be specified as a command-line argument and for subsequent command-line arguments to be used as strings to be provided as the argument to the methodmain. For example, using Sun's Java 2 SDK for Solaris, the command line

    java Terminator Hasta la vista Baby!
will start a Java virtual machine by invoking the methodmain of classTerminator (a class in an unnamed package) and passing it an array containing the four strings"Hasta","la","vista", and"Baby!".

We now outline the steps the virtual machine may take to executeTerminator, as an example of the loading, linking, and initialization processes that are described further in later sections.

The initial attempt to execute the methodmain of classTerminator discovers that the classTerminator is not loaded-that is, the virtual machine does not currently contain a binary representation for this class. The virtual machine then uses aClassLoader(§2.17.2) to attempt to find such a binary representation. If this process fails, an error is thrown. This loading process is described further in(§2.17.2).

AfterTerminator is loaded, it must be initialized beforemain can be invoked, and a type (class or interface) must always be linked before it is initialized. Linking(§2.17.3) involves verification, preparation, and (optionally) resolution.

Verification(§2.17.3) checks that the loaded representation ofTerminator is well formed, with a proper symbol table. Verification also checks that the code that implementsTerminator obeys the semantic requirements of the Java virtual machine. If a problem is detected during verification, an error is thrown.

Preparation(§2.17.3) involves allocation of static storage and any data structures that are used internally by the virtual machine, such as method tables.

Resolution(§2.17.3) is the process of checking symbolic references from classTerminator to other classes and interfaces, by loading the other classes and interfaces that are mentioned and checking that the references are correct.

The resolution step is optional at the time of initial linkage. An implementation may resolve a symbolic reference from a class or interface that is being linked very early, even to the point of resolving all symbolic references from the classes and interfaces that are further referenced, recursively. (This resolution may result in errors from further loading and linking steps.) This implementation choice represents one extreme and is similar to the kind of static linkage that has been done for many years in simple implementations of the C language.

An implementation may instead choose to resolve a symbolic reference only when it is actually used; consistent use of this strategy for all symbolic references would represent the "laziest" form of resolution. In this case, ifTerminator had several symbolic references to another class, the references might be resolved one at a time or perhaps not at all, if these references were never used during execution of the program.

The only requirement regarding when resolution is performed is that any errors detected during resolution must be thrown at a point in the program where some action is taken by the program that might, directly or indirectly, require linkage to the class or interface involved in the error. In the "static" example implementation choice described earlier, loading and linking errors could occur before the program is executed if they involved a class or interface mentioned in the classTerminator or any of the further, recursively referenced classes and interfaces. In a system that implemented the "laziest" resolution, these errors would be thrown only when a symbolic reference was used.

In our running example, the virtual machine is still trying to execute the methodmain of classTerminator. This is permitted only if the class has been initialized(§2.17.4).

Initialization consists of execution of any class variable initializers and static initializers of the classTerminator, in textual order. But beforeTerminator can be initialized, its direct superclass must be initialized, as well as the direct superclass of its direct superclass, and so on, recursively. In the simplest case,Terminator hasObject as its implicit direct superclass; if classObject has not yet been initialized, then it must be initialized beforeTerminator is initialized.

If classTerminator has another classSuper as its superclass, thenSuper must be initialized beforeTerminator. This requires loading, verifying, and preparingSuper, if this has not already been done, and, depending on the implementation, may also involve resolving the symbolic references fromSuper and so on, recursively.

Initialization may thus cause loading, linking, and initialization errors, including such errors involving other types.

Finally, after completion of the initialization for classTerminator (during which other consequential loading, linking, and initializing may have occurred), the methodmain ofTerminator is invoked.

2.17.2 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 compilerand constructing, from that binary form, aClass object to represent the class or interface. The binary format of a class or interface is normally theclass file format(see Chapter 4,"The class File Format").

The loading process is implemented by the classClassLoader and its subclasses. Different subclasses ofClassLoader may implement different loading policies. In particular, a class loader may cache binary representations of classes and interfaces, prefetch them based on expected usage, or load a group of related classes together. These activities may not be completely transparent to a running application if, for example, a newly compiled version of a class is not found because an older version is cached by a class loader. It is the responsibility of a class loader, however, to reflect loading errors only at points in the program where they could have arisen without prefetching or group loading.

If an error occurs during class loading, then an instance of one of the following subclasses of classLinkageError will be thrown at any point in the program that (directly or indirectly) uses the type:

2.17.3 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 differentactivities are involved in linking: verification, preparation, and resolution of symbolic references.

The Java programming language 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.

For example, an implementation may choose to resolve each symbolic reference in a class or interface individually, only when it is used (lazy or late resolution), or to resolve them all at once, for example, while the class is being verified (static resolution). This means that the resolution process may continue, in some implementations, after a class or interface has been initialized.

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 programming language.

If an error occurs during verification, then an instance of the following subclass of classLinkageError will be thrown at the point in the program that caused the class to be verified:

Preparation involves creating the static fields for a class or interface and initializing such fields to the standard default values(§2.5.1). This does not require the execution of any Java virtual machine code; explicit initializers for static fields are executed as part of initialization(§2.17.4), not preparation.

Implementations of the Java virtual machine may precompute additional data structures at preparation time in order to make later operations on a class or interface more efficient. One particularly useful data structure is a "method table" or other data structure that allows any method to be invoked on instances of a class without requiring a search of superclasses at invocation time.

The binary representation of a class or interface references other classes and interfaces and their fields, methods, and constructors symbolically, using the fully qualified names(§2.7.5) of the other classes and interfaces. For fields and methods these symbolic references include the name of the class or interface type that 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 undergoresolution, wherein a symbolic reference is validated 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 classIncompatibleClassChangeError, or of some other subclass, or ofIncompatibleClassChangeError itself (which is a subclass of the classLinkageError) may be thrown at any point in the program that uses a symbolic reference to the type:

2.17.4 Initialization

Initialization of a class consists of executing its static initializers(§2.11) and the initializersfor static fields(§2.9.2) declared in the class. Initialization of an interface consists of executing the initializers for fields declared in the interface(§2.13.3.1).

Before a class or interface is initialized, its direct 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.

A class or interface type T will beinitialized immediately before one of the following occurs:

Invocation of certain methods in library classes(§3.12) also causes class or interface initialization. See the Java 2 platform's class library specifications (for example, classClass and packagejava.lang.reflect) for details.

The intent here is that a type have a set of initializers that put it in a consistent state and that this state be the first state that is observed by other classes. The static initializers and class variable initializers are executed in textual order and may not refer to class variables declared in the class whose declarations appear textually after the use, even though these class variables are in scope. This restriction is designed to detect, at compile time, most circular or otherwise malformed initializations.

Before a class or interface is initialized its superclass is initialized, if it has not previously been initialized.

2.17.5 Detailed Initialization Procedure

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 virtualmachine is responsible for taking care of synchronization and recursive initializationby using the following procedure. It assumes that theClass object has already been verified and prepared and that theClass object contains state that can indicate one of four situations:

The procedure for initializing a class or interface is then as follows:

  1. Synchronize on theClass object that represents the class or interface to be initialized. This involves waiting until the current thread can obtain the lock for that object(§8.13).

  2. If initialization by some other thread is in progress for the class or interface, thenwait on thisClass object (which temporarily releases the lock). When the current thread awakens from thewait, repeat this step.

  3. If initialization is in progress for the class or interface by the current thread, then this must be a recursive request for initialization. Release the lock on theClass object and complete normally.

  4. If the class or interface has already been initialized, then no further action is required. Release the lock on theClass object and complete normally.

  5. If theClass object is in an erroneous state, then initialization is not possible. Release the lock on theClass object and throw aNoClassDefFoundError.

  6. Otherwise, record the fact that initialization of theClass object is now in progress by the current thread and release the lock on theClass object.

  7. Next, if theClass object represents a class rather than an interface, and the direct superclass of this class has not yet been initialized, then recursively perform this entire procedure for the uninitialized superclass. If the initialization of the direct superclass completes abruptly because of a thrown exception, then lock thisClass object, label it erroneous, notify all waiting threads, release the lock, and complete abruptly, throwing the same exception that resulted from the initializing the superclass.

  8. Next, execute either the class variable initializers and static initializers of the class or the field initializers of the interface, in textual order, as though they were a single block, except thatfinalstatic variables and fields of interfaces whose values are compile-time constants are initialized first.

  9. If the execution of the initializers completes normally, then lock thisClass object, label it fully initialized, notify all waiting threads, release the lock, and complete this procedure normally.

  10. Otherwise, the initializers must have completed abruptly by throwing some exception E. If the class of E is notError or one of its subclasses, then create a new instance of the classExceptionInInitializerError, with E as the argument, and use this object in place of E in the following step. But if a new instance ofExceptionInInitializerError cannot be created because anOutOfMemoryError occurs, then instead use anOutOfMemoryError object in place of E in the following step.

  11. Lock theClass object, label it erroneous, notify all waiting threads, release the lock, and complete this procedure abruptly with reason E or its replacement as determined in the previous step.
In some early implementations of the Java virtual machine, an exception duringclass initialization was ignored rather than allowing it to cause anExceptionInInitializerError as described here.

2.17.6 Creation of New Class Instances

A new class instance is explicitly created when one of the following situations occurs:

A new class instance may be implicitly created in the following situations:

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 anOutOfMemoryError. Otherwise, all the instance variables in the new object, including those declared in superclasses, are initialized to their default values(§2.5.1).

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 (usingthis), 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. If this constructor does not begin with an explicit constructor invocation of another constructor in the same class (usingthis) and is in a class other thanObject, then this constructor will begin with an explicit or implicit invocation of a superclass constructor (usingsuper). 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 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.
Unlike C++, the Java programming language does not specify altered rules for method dispatch during the creation of a new class instance. If methods are invoked that are overridden in subclasses in the object being initialized, then these overriding methods are used, even before the new object is completely created.

2.17.7 Finalization of Class Instances

The classObject has aprotected method calledfinalize; this method can be overridden by other classes. The particular definition offinalize that can be invoked for an object is called thefinalizer of that object. Before the storage for an object is reclaimed by the garbage collector, the Java virtual machine will invoke the finalizerof 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 programming 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. Nor does the language 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.

Thefinalize method declared in classObject takes no action. However, the fact that classObject declares afinalize method means that thefinalize method for any class can always invoke thefinalize method for its superclass, which is usually good practice. (Unlike constructors, finalizers do not automatically invoke the finalizer for the superclass; such an invocation must be coded explicitly.)

For efficiency, an implementation may keep track of classes that do not override thefinalize method of classObject or that override it in a trivial way, such as

    protected void finalize() { super.finalize(); }
We encourage implementations to treat such objects as having a finalizer that is not overridden and to finalize them more efficiently.

Thefinalize method may be invoked explicitly, just like any other method. However, doing so does not have any effect on the object's eventual automatic finalization.

The Java virtual machine imposes no ordering onfinalize method calls. Finalizers may be called in any order or even concurrently.

As an example, if a circularly linked group of unfinalized objects becomes unreachable, then all the objects may become finalizable together. Eventually, the finalizers for these objects may be invoked in any order or even concurrently using multiple threads. If the automatic storage manager later finds that the objects are unreachable, then their storage can be reclaimed.

2.17.8 Unloading of Classes and Interfaces

A class or interface may be unloaded if and only if its class loader is unreachable. The bootstrap class loader is always reachable; as a result, system classes may never be unloaded.

2.17.9 Virtual Machine Exit

The Java virtual machine terminates all its activity and exits when one of two things happens:

A program can specify that all finalizers that have not been automatically invoked are to be run before the virtual machine exits. This is done by invoking the methodrunFinalizersOnExit of the classSystem with the argumenttrue.4 By default finalizers are not run on exit. Once running finalizers on exit has been enabled it may be disabled by invokingrunFinalizersOnExit with the argumentfalse. An invocation of therunFinalizersOnExit method is permitted only if the caller is allowed toexit and is otherwise rejected by the security manager.


2.18 FP-strict Expressions

If the type of an expression is float or double, then there is a question as to what value set(§2.4.3) the value of the expression may be drawn from. This is governed by the rules of value set conversion(§2.6.6); these rules in turn depend on whether or not the expression isFP-strict.

Every compile-time constant expression is FP-strict. If an expression is not a compile-time constant expression, then consider all the class declarations, interface declarations, and method declarations that contain the expression. Ifany such declaration bears the strictfp modifier, then the expression is FP-strict.

It follows that an expression is not FP-strict if and only if it is not a compile-time constant expressionand it does not appear within any declaration that has the strictfp modifier.

Within an FP-strict expression, all intermediate values must be elements of the float value set or the double value set, implying that the results of all FP-strict expressions must be those predicted by IEEE 754 arithmetic on operands represented using single and double formats. Within an expression that is not FP-strict, some leeway is granted for an implementation to use an extended exponent range to represent intermediate results; the net effect, roughly speaking, is that a calculation might produce "the correct answer" in situations where exclusive use of the float value set or double value set might result in overflow or underflow.


2.19 Threads

While most of the preceding discussion is concerned only with the behavior of code as executed by a single thread, the Java virtual machine can support many threads of execution at once. These threads independently execute code that operates on values and objects residing in a shared main memory. Threads may be supported by having many hardware processors, by time-slicing a single hardware processor, or by time-slicing many hardware processors.

Any thread may be marked as adaemon thread. When code running in some thread creates a newThread object, that new thread is initially marked as a daemon thread if and only if the creating thread is a daemon thread. A program can change whether or not a particular thread is a daemon thread by calling thesetDaemon method in classThread. The Java virtual machine initially starts up with a single nondaemon thread, which typically calls the methodmain of some class. The virtual machine may also create other daemon threads for internal purposes. The Java virtual machine exits when all nondaemon threads have terminated(§2.17.9).

By providing mechanisms forsynchronizing the concurrent activity of threads, the Java programming language supports the coding of programs that, though concurrent, still exhibit deterministic behavior. To synchronize threads the language usesmonitors, a mechanism for allowing one thread at a time to execute a region of code. The behavior of monitors is explained in terms oflocks. There is a lock associated with each object.

Thesynchronized statement performs two special actions relevant only to multithreaded operation:

  1. After computing a reference to an object but before executing its body, it locks a lock associated with the object.

  2. After execution of the body has completed, either normally or abruptly, it unlocks that same lock. As a convenience, a method may be declaredsynchronized; such a method behaves as if its body were contained in asynchronized statement.
The methodswait,notify, andnotifyAll of classObject support an efficient transfer of control from one thread to another. Rather than simply "spinning" (repeatedly locking and unlocking an object to see whether some internal state has changed), which consumes computational effort, a thread can suspend itself usingwait until such time as another thread awakens it usingnotify ornotifyAll. This is especially appropriate in situations where threads have a producer-consumer relationship (actively cooperating on a common goal) rather than a mutual exclusion relationship (trying to avoid conflicts while sharing a common resource).

As a thread executes code, it carries out a sequence of actions. A thread mayuse the value of a variable orassign it a new value. (Other actions include arithmetic operations, conditional tests, and method invocations, but these do not involve variables directly.) If two or more concurrent threads act on a shared variable, there is a possibility that the actions on the variable will produce timing-dependent results. This dependence on timing is inherent in concurrent programming and produces one of the few situations where the result of a program is not determined solely byThe Java Language Specification.

Each thread has a working memory, in which it may keep copies of the values of variables from the main memory that are shared between all threads. To access a shared variable, a thread usually first obtains a lock and flushes its working memory. This guarantees that shared values will thereafter be loaded from the shared main memory to the working memory of the thread. By unlocking a lock, a thread guarantees that the values held by the thread in its working memory will be written back to the main memory.

The interaction of threads with the main memory, and thus with each other, may be explained in terms of certain low-level actions. There are rules about the order in which these actions may occur. These rules impose constraints on any implementation of the Java programming language. A programmer may rely on the rules to predict the possible behaviors of a concurrent program. The rules do, however, intentionally give the implementor certain freedoms. The intent is to permit certain standard hardware and software techniques that can greatly improve the speed and efficiency of concurrent code.

Briefly put, the important consequences of the rules are the following:

The details of the interaction of threads with the main memory, and thus with each other, are discussed in detail in Chapter8,"Threads and Locks."


1 Including updates for JDK release 1.1 and the Java 2 platform, v1.2, published athttp://java.sun.com.

2 Note that a local variable is not initialized on its creation and is considered to hold a value only once it is assigned(§2.5.1).

3UnsupportedClassVersionError, a subclass ofClassFormatError, was introduced in the Java 2 platform, v1.2, to enable easy identification of aClassFormatError caused by an attempt to load a class represented using an unsupported version of theclass file format.

4 The methodrunFinalizersOnExit was first implemented in JDK release 1.1 but has been deprecated in the Java 2 platform, v1.2.

Contents |Prev |Next |Index

Virtual Machine Specification
Copyright © 1999 Sun Microsystems, Inc.All rights reserved
Please send any comments or corrections through ourfeedback form


[8]ページ先頭

©2009-2025 Movatter.jp