目次 | | | 索引 Java言語規定
第2版

12. 実行
Execution

12.では,プログラムの実行中に発生する活動を規定する。12.は,Java仮想計算機,並びにプログラムを形成する,クラス,インタフェース及びオブジェクトのライフサイクルに関して示す。

This chapter specifies activities that occur during execution of a program. It is organized around the life cycle of a Java virtual machine and of the classes, interfaces, and objects that form a program.

Java仮想計算機は,指定されたクラスをロードし,この指定されたクラスにおけるメソッドmainを呼び出すことによって,処理を開始する。12.1では,mainの実行に含まれるロード,リンク及び初期化の段階を,12.における諸概念の導入として概説する。それ以降では,ロード(12.2),リンク(12.3)及び初期化(12.4)の詳細を規定する。

A Java virtual machine starts up by loading a specified class and then invoking the method main in this specified class. Section §12.1 outlines the loading, linking, and initialization steps involved in executing main, as an introduction to the concepts in this chapter. Further sections specify the details of loading (§12.2), linking (§12.3), and initialization (§12.4).

12.では,続けて,新しいクラスインスタンスの生成(12.5),クラスインスタンスの終了(12.6)の手続きを規定する。最後に,クラスのアンロード(12.7)及びプログラムが処理を抜けるときの手続き(12.8)を規定する。

The chapter continues with a specification of the procedures for creation of new class instances (§12.5); and finalization of class instances (§12.6). It concludes by describing the unloading of classes (§12.7) and the procedure followed when a program exits (§12.8).

12.1 仮想計算機の開始
Virtual Machine Start-Up

Java仮想計算機は,ある指定されたクラスのメソッドmainを呼び出し,文字列の配列である一つの引数をそのメソッドに渡すことによって,実行を開始する。この規定の例では,この最初のクラスを典型的にTestと呼ぶことにする。
A Java virtual machine starts execution by invoking the method main of some specified class, passing it a single argument, which is an array of strings. In the examples in this specification, this first class is typically called Test.

仮想計算機の開始についての正確な意味は,The Java Virtual Machine Specification, Second Edition の5.で与えられる。12.1では,Javaプログラム言語の観点から,処理の概観を示す。

The precise semantics of virtual machine start-up are given in chapter 5 of The Java Virtual Machine Specification, Second Edition. Here we present an overview of the process from the viewpoint of the Java programming language.

開始のクラスをJava仮想計算機に指定する方法はこの規定の範囲外とするが,コマンド行を使用するホスト環境では,コマンド行の引数の一つとしてクラスの完全限定名を指定し,それに続くコマンド行の引数をメソッドmainへの引数として与える文字列として使用することが,典型的である。例えば,UNIXでの実装では,コマンド行は次のとおりとなる。

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 following command-line arguments to be used as strings to be provided as the argument to the method main. For example, in a UNIX implementation, the command line:

java Test reboot Bob Dot Enzo
これは,クラスTest(これは,名前無しパッケージにおけるクラスである。)のメソッドmainを呼び出し,そのクラスに四つの文字列"reboot", "Bob", "Dot"及び"Enzo"を含む一つの配列を渡すことによって,Java仮想計算機を開始することになる。
will typically start a Java virtual machine by invoking method main of class Test (a class in an unnamed package), passing it an array containing the four strings "reboot", "Bob", "Dot", and "Enzo".

次に,仮想計算機がTestを実行するために行う処理の段階の概略を,ロード処理,リンク処理及び初期化処理の例として示す。これらの処理の詳細は,12.2から12.4で述べる。

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

12.1.1 クラスTestのロード
Load the Class Test

クラスTestのメソッドmainを実行しようとする最初の試みでは,クラスTestがロードされていないこと,すなわち,仮想計算機が現時点でこのクラスに対するバイナリ表現を含まないことを発見する。そして,仮想計算機は,クラスローダを使用して,そのバイナリ表現を見つけようと試みる。この処理が失敗する場合には,エラーが投げられる。このロード処理は,12.2で詳しく示す。
The initial attempt to execute the method main of class Test discovers that the class Test is not loaded-that is, that the virtual machine does not currently contain a binary representation for this class. The virtual machine then uses a class loader to attempt to find such a binary representation. If this process fails, then an error is thrown. This loading process is described further in §12.2.

12.1.2 Testのリンク: 検証,準備及び(オプションの)記号解決
Link Test: Verify, Prepare, (Optionally) Resolve

Testをロードした後,mainを呼び出す前に,Testを初期化しなければならない。さらに,Testは,すべての(クラス又はインタフェース)型と同様に,初期化の前にリンクされなければならない。リンクには,検証,準備及び(オプションの)記号解決を含む。リンクは,12.3で詳しく示す。
After Test is loaded, it must be initialized before main can be invoked. And Test, like all (class or interface) types, must be linked before it is initialized. Linking involves verification, preparation and (optionally) resolution. Linking is described further in §12.3.

検証は,Testのロードされた表現が,適切な記号表をもった正しい形式であるか検査する。検証は,さらに,Testを実装するコードが,Javaプログラム言語及びJava仮想計算機の意味要件に従っているかも検査する。検証中に問題を検出した場合は,エラーが投げられる。検証は,12.3.1で詳しく示す。

Verification checks that the loaded representation of Test is well-formed, with a proper symbol table. Verification also checks that the code that implements Test obeys the semantic requirements of the Java programming language and the Java virtual machine. If a problem is detected during verification, then an error is thrown. Verification is described further in §12.3.1.

準備は,静的記憶領域の割当て,及びメソッド表などの仮想計算機によって内部的に使用されるデータ構造の割当てを含む。準備は,12.3.2で詳しく示す。

Preparation involves allocation of static storage and any data structures that are used internally by the virtual machine, such as method tables. Preparation is described further in §12.3.2.

記号解決は,記述された他のクラス及びインタフェースをロードし,参照が正しいことを検査することによって,Testから他のクラス及びインタフェースへの記号参照を検査する処理とする。

Resolution is the process of checking symbolic references from Test to other classes and interfaces, by loading the other classes and interfaces that are mentioned and checking that the references are correct.

記号解決の段階は,初期のリンク時にはオプションとする。実装によっては,非常に早い段階でリンクされることになっているクラス又はインタフェースからの記号参照を解決してもよい。これには,再帰的に参照されるクラス及びインタフェースからの記号参照すべての解決を含んでもよい。(ただし,この記号解決は,以降のロード及びリンクにおいてエラーを生じるかもしれない。)この実装の選択は極端な例であるが,C言語の単純な実装で長年行われてきた"静的"リンクの種類に類似している。(これらの実装では,コンパイルされたプログラムは,通常"a.out"ファイルとして表現する。このファイルは,そのプログラムが使用するライブラリルーチンへの完全に解決されたリンクを含んだ,プログラムの完全にリンクされた版を保持している。これらライブラリルーチンのコピーが,"a.out"ファイルに含まれている。)

The resolution step is optional at the time of initial linkage. An implementation may resolve symbolic references 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 these 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. (In these implementations, a compiled program is typically represented as an "a.out" file that contains a fully-linked version of the program, including completely resolved links to library routines used by the program. Copies of these library routines are included in the "a.out" file.)

この代わりに,実装によっては,記号参照を実際に使用する場合にだけ解決する方法を選択してもよい。すべての記号参照に対してこの戦略を一貫して使用すると,"もっとも怠慢な"形式の記号解決になる。

An implementation may instead choose to resolve a symbolic reference only when it is actively used; consistent use of this strategy for all symbolic references would represent the "laziest" form of resolution.

この場合,Testが他のクラスへの幾つかの記号参照をもっていたとすると,それらの参照を使用するときに,一度に一つ解決するかもしれないし,プログラムの実行中にそれらの参照を一度も使用しなければ,全く解決しないかもしれない。

In this case, if Test had several symbolic references to another class, then the references might be resolved one at a time, as they are used, or perhaps not at all, if these references were never used during execution of the program.

記号解決を実行するときのただ一つの要件は,記号解決中にエラーを検出した場合,そのエラーに関連するクラス又はインタフェースへのリンクを直接的に又は間接的に要求するかもしれないプログラムが動作を実行する箇所で,そのエラーを投げなければならないこととする。上記の"静的な"実装選択の例では,クラスTestにおいて記述されているクラス若しくはインタフェース,又はさらなる再帰的に参照されるクラス及びインタフェースにロード及びリンクのエラーが関連するとしたら,これらエラーは,プログラムが実行される前に発生可能となる。"もっとも怠慢な"記号解決を実装したシステムでは,不正な記号参照を実際に使用した場合にだけ,これらのエラーが投げられる。

The only requirement on 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. Using the "static" example implementation choice described above, loading and linkage errors could occur before the program is executed if they involved a class or interface mentioned in the class Test 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 an incorrect symbolic reference is actively used.

記号解決の過程の詳細については,12.3.3で示す。

The resolution process is described further in §12.3.3.

12.1.3 Testの初期化: 初期化子の実行
Initialize Test: Execute Initializers

これまでに使用してきた例では,仮想計算機は,まだ,クラスTestのメソッドmainを実行しようとしているところである。これは,そのクラスを初期化した場合(12.4.1)にだけ実行できる。
In our continuing example, the virtual machine is still trying to execute the method main of class Test. This is permitted only if the class has been initialized (§12.4.1).

初期化は,あらゆるクラス変数の初期化子及びクラスTestの静的初期化子を,記述した順序で実行することから成る。しかし,Testが初期化可能となる前に,直接的上位クラスを初期化しなければならない。同様に,その直接的上位クラスの直接的上位クラスが存在する場合は,それを初期化しなければならない。以降も再帰的に同様とする。もっとも単純な場合は,Testが,暗黙的な直接的上位クラスとしてObjectをもつ。クラスObjectをまだ初期化していない場合には,それをTestよりも前に初期化しなければならない。クラスObjectは上位クラスをもたないので,再帰はここで終了する。

Initialization consists of execution of any class variable initializers and static initializers of the class Test, in textual order. But before Test 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, Test has Object as its implicit direct superclass; if class Object has not yet been initialized, then it must be initialized before Test is initialized. Class Object has no superclass, so the recursion terminates here.

クラスTestに上位クラスとしてクラスSuperがある場合,Testよりも前にSuperを初期化しなければならない。これには,Superのロード,検証及び準備が必要であって,実装によっては,Super及び同様に再帰的に続く上位クラスからの記号参照の解決を含んでもよい。

If class Test has another class Super as its superclass, then Super must be initialized before Test. This requires loading, verifying, and preparing Super if this has not already been done and, depending on the implementation, may also involve resolving the symbolic references from Super and so on, recursively.

したがって,初期化では,他の型に関連するエラーなどを含んだ,ロード,リンク及び初期化のエラーが発生するかもしれない。

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

初期化の過程の詳細については,12.4で示す。

The initialization process is described further in §12.4.

12.1.4 Test.mainの呼出し
Invoke Test.main

最終的に,クラスTestの初期化(この初期化中に,他のロード,リンク及び初期化が結果として生じるかもしれない。)が完了した後で,Testのメソッドmainを呼び出す。
Finally, after completion of the initialization for class Test (during which other consequential loading, linking, and initializing may have occurred), the method main of Test is invoked.

メソッドmainは,publicstatic及びvoidとして宣言しなければならない。このメソッドは,文字列の配列である単一の実引数を受理しなければならない。

The method main must be declared public, static, and void. It must accept a single argument that is an array of strings.

12.2 クラス及びインタフェースのロード
Loading of Classes and Interfaces

ロード(loading) は,特定の名前をもつクラス又はインタフェースの型のバイナリ形式を見つけ出し,そのバイナリ形式から,クラス又はインタフェースを表現するClassオブジェクトを構築する過程を意味する。この場合,バイナリ形式の見つけ出しは,恐らくその実行の最中に計算することによっても可能だが,より典型的には,コンパイラによってあらかじめソ−スコ−ドから計算されたバイナリ表現を検索することによって実行される。
Loading refers to the process of finding the binary form of a class or interface type with a particular name, perhaps by computing it on the fly, but more typically by retrieving a binary representation previously computed from source code by a compiler, and constructing, from that binary form, a Class object to represent the class or interface.

ロードの正確な意味は,The Java Virtual Machine Specification, Second Edition の5.で与えられる。12.2では,Javaプログラム言語の観点からその処理の概要を示す。

The precise semantics of loading are given in chapter 5 of The Java Virtual Machine Specification, Second Edition. Here we present an overview of the process from the viewpoint of the Java programming language.

クラス又はインタフェースのバイナリ形式は,通常,前段落で示した The Java Virtual Machine Specification, Second Edition で示されたclassファイル形式とする。しかし,13.1に規定される要件を満たしていれば,他の形式も可能とする。クラスClassLoaderのメソッドdefineClassを使用して,classファイル形式のバイナリ表現からClassオブジェクトを構築できる。

The binary format of a class or interface is normally the class file format described in The Java Virtual Machine Specification cited above, but other formats are possible, provided they meet the requirements specified in §13.1. The method defineClass of class ClassLoader may be used to construct Class objects from binary representations in the class file format.

正しく振る舞うクラスローダは,次の特性を維持する。

Well-behaved class loaders maintain these properties:

悪意のあるクラスローダは,これらの特性に違反することもある。しかし,型システムのセキュリティの土台をくずすことはできない。これは,Java仮想計算機がこれに対して防御するからである。
A malicious class loader could violate these properties. However, it could not undermine the security of the type system, because the Java virtual machine guards against this.

これらの課題のより詳細に関しては,The Java Virtual Machine Specification, Second Edition を参照するか,ACM SIGPLAN Notices, Volume 33, Number 10, October 1998として出版されている Proceedings of OOPSLA '98 の36ページ〜44ページにあるSheng Liang及びGilad Brachaの論文 Dynamic Class Loading in the Java Virtual Machine を参照すること。Javaプログラム言語の設計の基本原理は,型システムが,その言語で記述されたコードによって,特にClassLoader及びSecurityManagerといった普通ならば影響を与えやすいシステムクラスの実装によってさえも,破壊されることがないということとする。

For further discussion of these issues, see The Java Virtual Machine Specification, Second Edition and the paper Dynamic Class Loading in the Java Virtual Machine, by Sheng Liang and Gilad Bracha, in Proceedings of OOPSLA '98, published as ACM SIGPLAN Notices, Volume 33, Number 10, October 1998, pages 36-44. A basic principle of the design of the Java programming language is that the type system cannot be subverted by code written in the language, not even by implementations of such otherwise sensitive system classes as ClassLoader and SecurityManager.

12.2.1 ロード処理
The Loading Process

ロード処理は,クラスClassLoader及びその下位クラスによって実装される。ClassLoaderの異なる下位クラスは,異なるロードの方針を実装してもよい。特に,クラスローダは,クラス及びインタフェースのバイナリ表現をキャッシュし,予想される使用方法に基づいてそれらを事前に取り出し,関係するクラスのグループを一緒にロードしてよい。これらの活動は,実行中のアプリケーションに対して完全に透過的でなくてもよい。例えば,クラスローダが古い版をキャッシュしているので,新たにコンパイルした版が見つからないような場合もある。しかし,ロードエラーが事前取出し又はグループロードを行わない場合にも発生する可能性があるプログラムにおいて,その場所でだけ,そのエラーを反映するのは,クラスローダの責任とする。
The loading process is implemented by the class ClassLoader and its subclasses. Different subclasses of ClassLoader 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 they could have arisen without prefetching or group loading.

クラスをロード中にエラーが発生した場合には,その型を(直接的に又は間接的に)使用するプログラムの中の任意の場所で,クラスLinkageErrorの下位クラスの次のいずれか一つのインスタンスが投げられる。

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

ロードは,新しいデータ構造の割当てを含むので,OutOfMemoryErrorで失敗することもある。
Because loading involves the allocation of new data structures, it may fail with an OutOfMemoryError.

12.3 クラス及びインタフェースのリンク
Linking of Classes and Interfaces

リンク(linking) は,クラス又はインタフェースの型のバイナリ形式を取り出し,Java仮想計算機の実行時の状態に結合する処理とする。これによって,実行可能となる。クラス又はインタフェースの型は,常にリンクの前にロードされる。
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.

リンクは,検証,準備及び記号参照解決の三つの異なる処理を含む。リンクの正確な意味は,The Java Virtual Machine Specification, Second Edition の5.で与えられる。12.3では,Javaプログラム言語の観点から処理の概要を示す。

Three different activities are involved in linking: verification, preparation, and resolution of symbolic references.The precise semantics of linking are given in chapter 5 of The Java Virtual Machine Specification, Second Edition. Here we present an overview of the process from the viewpoint of the Java programming language.

この規定では,リンク処理(及びそれに関係するロード処理)を実行する時について,実装に柔軟性を与えている。ただし,言語の意味規則を守ること,クラス又はインタフェースの初期化の前に完全に検証及び準備をすること,並びにリンク中に検出したエラーを,そのエラーに関連するクラス又はインタフェースへのリンクを要求するかもしれないプログラムが動作を実行した時点で投げること,という条件を満たすものとする。

This specification 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 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.

リンクは,新しいデータ構造の割当てを含むので,OutOfMemoryErrorで失敗することもある。

Because linking involves the allocation of new data structures, it may fail with an OutOfMemoryError.

12.3.1 バイナリ表現の検証
Verification of the Binary Representation

検証(veritication) では,クラス又はインタフェースのバイナリ表現が構造的に正しいことを確認する。例えば,すべての命令が妥当な演算コードをもっていること,すべての分岐命令が他の命令の中間ではなく先頭へと分岐していること,すべてのメソッドが構造的に正しいシグネチャをもっていること,すべての命令がJava仮想計算機の型原理に従っていることなどを調べる。
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 virtual machine language.

検証処理の規定に関しては,The Java Virtual Machine Specification, Second Edition を参照すること。

For the specification of the verification process, see the separate volume of this series, The Java Virtual Machine Specification, Second Edition.

検証中にエラーが発生した場合は,プログラムにおける,そのクラスの検証を引き起こした場所で,クラスLinkageErrorの下位クラスである次のインスタンスが投げられる。

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

12.3.2 クラス又はインタフェースの型の準備
Preparation of a Class or Interface Type

準備(preparation)は,クラス又はインタフェースのstaticフィールド(クラス変数及びクラス定数)の生成及びそれらフィールドのデフォルト値への初期化(4.5.5)を含む。準備では,ソースコードの実行を要求しない。staticフィールドの明示的な初期化子は,準備ではなく初期化(12.4)の一部として実行される。
Preparation involves creating the static fields (class variables and constants) for a class or interface and initializing such fields to the default values (§4.5.5). This does not require the execution of any source code; explicit initializers for static fields are executed as part of initialization (§12.4), not preparation.

Java仮想計算機の実装は,クラス又はインタフェースにおける後の操作をより効率的にするために.準備の時に付加的なデータ構造を事前に計算してもよい。特に役に立つデータ構造としては,"メソッド表"又はクラスのインスタンスにおいてメソッドを起動する時に上位クラスの検索を要求することなしに起動可能とする他のデータ構造がある。

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.

12.3.3 記号参照の解決
Resolution of Symbolic References

クラス又はインタフェースのバイナリ表現は,他のクラス及びインタフェースのバイナリ名(13.1)を使用し,他のクラス及びインタフェース,並びにそれらのフィールド,メソッド及びコンストラクタを記号的に参照する(13.1)。フィールド及びメソッドに対して,これらの記号参照は,そのフィールド又はメソッドそれ自体の名前だけでなく,そのフィールド又はメソッドを宣言しているクラス又はインタフェースの型の名前を,適切な型情報とともに含む。
The binary representation of a class or interface references other classes and interfaces and their fields, methods, and constructors symbolically, using the binary names (§13.1) of the other classes and interfaces (§13.1). 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.

記号参照が使用可能となる前に,解決(resolution)を行わなければならない。解決において,記号参照が正しいことが検査され,通常は,その参照が再帰的に使用されている場合には,より効率的に処理可能な直接的参照に置換する。

Before a symbolic reference can be used it must undergo resolution, wherein a symbolic reference is checked to be correct and, typically, replaced with a direct reference that can be more efficiently processed if the reference is used repeatedly.

解決中にエラーが発生した場合は,エラーが投げられる。通常このエラ−は,クラス IncompatibleClassChangeErrorの次に示す下位クラスのうちの一つのインスタンスとするが,クラスIncompatibleClassChangeErrorのこれ以外の下位クラスのインスタンスであってもよいし,クラスIncompatibleClassChangeErrorそれ自体のインスタンスであってもよい。このエラーは,その型への記号参照を直接的に又は間接的に使用するプログラムにおける任意の時点で投げられてよい。

If an error occurs during resolution, then an error will be thrown. Most typically, this will be an instance of one of the following subclasses of the class IncompatibleClassChangeError, but it may also be an instance of some other subclass of IncompatibleClassChangeError or even an instance of the class IncompatibleClassChangeError itself. This error may be thrown at any point in the program that uses a symbolic reference to the type, directly or indirectly:

例えばこれは,元々publicとして宣言していたフィールドを,そのフィールドを参照する他のクラスをコンパイルした後で,privateに変更した場合に発生する(13.4.6)
This can occur, for example, if a field that is originally declared public is changed to be private after another class that refers to the field has been compiled (§13.4.6).

例えばこれは,元々abstractではなかったクラスを,そのクラスを参照する他のクラスをコンパイルした後で,abstractに変更した場合に発生する(13.4.1)
This can occur, for example, if a class that is originally not abstract is changed to be abstract after another class that refers to the class in question has been compiled (§13.4.1).

例えばこれは,そのフィールドを参照する他のクラスをコンパイルした後で,クラスからフィールドの宣言を削除した場合に発生する(13.4.7)
This can occur, for example, if a field declaration was deleted from a class after another class that refers to the field was compiled (§13.4.7).

例えばこれは,そのメソッドを参照する他のクラスをコンパイルした後で,クラスからメソッドの宣言を削除した場合に発生する(13.4.11)
This can occur, for example, if a method declaration was deleted from a class after another class that refers to the method was compiled (§13.4.11).

さらに,あるクラスでnativeメソッドを宣言しており,その実装が見つからない場合,UnsatisfiedLinkError(LinkageErrorの下位クラス)が投げられてもよい。このエラーは,仮想計算機が使用している解決の戦略の種類に応じて,メソッドを使用したとき又はそれ以前に発生する(12.3)

Additionally, an UnsatisfiedLinkError (a subclass of LinkageError) may be thrown if a class declares a native method for which no implementation can be found. The error will occur if the method is used, or earlier, depending on what kind of resolution strategy is being used by the virtual machine (§12.3).

12.4 クラス及びインタフェースの初期化
Initialization of Classes and Interfaces

クラスの初期化は,クラスの静的初期化子及びそのクラスで宣言されているstaticフィールド(クラス変数)の初期化子の実行で構成される。インタフェースの初期化は,そのインタフェースで宣言されているフィールド(定数)の初期化子の実行で構成される。
Initialization of a class consists of executing its static initializers and the initializers for static fields (class variables) declared in the class. Initialization of an interface consists of executing the initializers for fields (constants) declared there.

クラスを初期化する前に,その上位クラスを初期化しなければならないが,そのクラスが実装するインタフェースは初期化しない。同様に,インタフェースを初期化する前に,そのインタフェースの上位インタフェースは初期化しない。

Before a class is initialized, its superclass must be initialized, but interfaces implemented by the class are not initialized. Similarly, the superinterfaces of an interface are not initialized before the interface is initialized.

12.4.1 初期化の発生時点
When Initialization Occurs

クラスの 初期化(initialization) は,クラスの静的初期化子及びそのクラスで宣言されている静的フィールドの初期化子の実行で構成される。インタフェースの 初期化(initialization) は,そのインタフェースで宣言されているフィールドの初期化子の実行で構成される。
Initialization of a class consists of executing its static initializers and the initializers for static fields declared in the class. Initialization of an interface consists of executing the initializers for fields declared in the interface.

クラスを初期化する前に,その直接的上位クラスを初期化しなければならないが,そのクラスが実装するインタフェースを初期化する必要はない。同様に,インタフェースを初期化する前に,そのインタフェースの上位インタフェースを初期化する必要はない。

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

クラス又はインタフェースの型 T は,次のいずれか一つが最初に起こる直前に初期化される。

A class or interface type T will be initialized immediately before the first occurrence of any one of the following:

クラス Class 及びパッケージ java.lang.reflect における自己反映的なメソッドの中にも,呼び出されるとクラス又はインタフェースの初期化を引き起こすものがある。クラス又はインタフェースは,これら以外のいかなる状況においても初期化されない。
Invocation of certain reflective methods in class Class and in package java.lang.reflect also causes class or interface initialization. A class or interface will not be initialized under any other circumstance.

ここでの意図は,クラス又はインタフェースの型にはそれを一貫した状態にする初期化子の集合があって,その状態が他のクラスによって観察される初期状態になる,ということにある。静的初期化子及びクラス変数初期化子は,テキスト(ソースコード)で記述された順番に実行され,それらは,テキスト順で使用する後に宣言が現れるクラスの中で宣言されているクラス変数を,たとえそのクラス変数が有効範囲内にあったとしても,参照してはならない(8.3.2.3)。この制限は,ほとんどの循環した初期化又はその他の不正な形式の初期化を,コンパイル時に検出するために設計されている。

The intent here is that a class or interface type has a set of initializers that put it in a consistent state, and that this state is the first state that is observed by other classes. 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 (§8.3.2.3). This restriction is designed to detect, at compile time, most circular or otherwise malformed initializations.

8.3.2.3の例に示すとおり,初期化コードを制限していないことによって,その初期化式を評価する前のまだデフォルト値をもっているときに,クラス変数の値を調べることが可能な例を作成できる。しかし,これらの例は,実際にはほとんどない。同様の例は,インスタンス変数の初期化についても作成できる。12.5の最後の例を参照すること。これら初期化では,Java言語のあらゆる能力が使用できる。プログラマは注意して使用しなければならない。この能力によってコード生成には余分な負荷がかかるが,この負荷は,Java言語が並行的であるためにいずれにしても発生する(12.4.3)

As shown in an example in §8.3.2.3, the fact that initialization code is unrestricted allows examples to be constructed where the value of a class variable can be observed when it still has its initial default value, before its initializing expression is evaluated, but such examples are rare in practice. (Such examples can be also constructed for instance variable initialization; see the example at the end of §12.5). The full power of the language is available in these initializers; programmers must exercise some care. This power places an extra burden on code generators, but this burden would arise in any case because the language is concurrent (§12.4.3).

クラスを初期化する前に,その上位クラスを初期化していない場合は,その上位クラスを初期化する。

Before a class is initialized, its superclasses are initialized, if they have not previously been initialized.

次に例を示す。

Thus, the test program:

class Super {
	static { System.out.print("Super "); }
}
class One {
	static { System.out.print("One "); }
}
class Two extends Super {
	static { System.out.print("Two "); }
}
class Test {
	public static void main(String[] args) {
		One o = null;
		Two t = new Two();
		System.out.println((Object)o == (Object)t);
	}
}
これは次を出力する。
prints:

Super Two false
クラスOneは初期化されない。これは,能動的に使用されておらず,したがってリンクされないことによる。クラスTwoは,その上位クラスSuperが初期化された後にだけ初期化される。
The class One is never initialized, because it not used actively and therefore is never linked to. The class Two is initialized only after its superclass Super has been initialized.

クラスフィールドへの参照は,そのフィールドが,下位クラスの名前,下位インタフェースの名前,又はインタフェースを実装するクラスの名前を介して参照される場合であっても,そのフィールドを実際に宣言するクラス又はインタフェースだけの初期化を引き起こす。

A reference to a class field causes initialization of only the class or interface that actually declares it, even though it might be referred to through the name of a subclass, a subinterface, or a class that implements an interface.

次に例を示す。

The test program:

class Super { static int taxi = 1729; }
class Sub extends Super {
	static { System.out.print("Sub "); }
}
class Test {
	public static void main(String[] args) {
		System.out.println(Sub.taxi);
	}
}
これは次だけを印字する。
prints only:

1729
これは,クラスSubを初期化しないことによる。Sub.taxiへの参照は,クラスSuperで実際に宣言しているフィールドへの参照であって,クラスSubの初期化を引き起こさない。
because the class Sub is never initialized; the reference to Sub.taxi is a reference to a field actually declared in class Super and does not trigger initialization of the class Sub.

インタフェースの初期化は,それ自体では,その上位インタフェースの初期化を引き起こさない。

Initialization of an interface does not, of itself, cause initialization of any of its superinterfaces.

この例を次に示す。

Thus, the test program:

interface I {
	int i = 1, ii = Test.out("ii", 2);
}
interface J extends I {
	int j = Test.out("j", 3), jj = Test.out("jj", 4);
}
interface K extends J {
	int k = Test.out("k", 5);
}
class Test {
	public static void main(String[] args) {
		System.out.println(J.i);
		System.out.println(K.j);
	}
	static int out(String s, int i) {
		System.out.println(s + "=" + i);
		return i;
	}
}
これは次の出力を生成する。
produces the output:

1
j=3
jj=4
3

J.iへの参照は,コンパイル時の定数であるフィールドへの参照となる。したがって,それはIの初期化を引き起こさない。K.jへの参照は,コンパイル時の定数ではない,インタフェースJにおいて実際に宣言されているフィールドへの参照となる。これは,インタフェースJのフィールドの初期化を引き起こすが,上位インタフェースIのフィールド及びインタフェースKのフィールドの初期化は引き起こさない。インタフェースJのフィールドjを参照するために,Kという名前を使用しているにもかかわらず,インタフェースKは初期化されない。
The reference to J.i is to a field that is a compile-time constant; therefore, it does not cause I to be initialized. The reference to K.j is a reference to a field actually declared in interface J that is not a compile-time constant; this causes initialization of the fields of interface J, but not those of its superinterface I, nor those of interface K. Despite the fact that the name K is used to refer to field j of interface J, interface K is not initialized.

12.4.2 初期化手続きの詳細
Detailed Initialization Procedure

Javaプログラム言語はマルチスレッド対応であるために,ある他のスレッドが,同時に同じクラス又はインタフェースの初期化を試みるかもしれないので,クラス又はインタフェースの初期化には注意深い同期を必要とする。あるクラス又はインタフェースの初期化が,そのクラス又はインタフェースの初期化の一部として再帰的に要求される可能性もある。例えば,クラス A における変数初期化子が,無関係であるクラス B のメソッドを呼び出すかもしれず,これが,結果としてクラス A のメソッドを呼び出す可能性がある。Java仮想計算機の実装は,次の手続きを使用することによって,同期と再帰的な初期化とを注意深く扱う責任がある。ここで,そのオブジェクトClassは,既に検証済み及び準備済みであること,並びにそのオブジェクトClassは,次の四つの状況の一つを示す状態を含むことを仮定する。
Because the Java programming language is multithreaded, initialization of a class or interface requires careful synchronization, since some other thread may be trying to initialize the same class or interface at the same time. There is also the possibility that initialization of a class or interface may be requested recursively as part of the initialization of that class or interface; for example, a variable initializer in class A might invoke a method of an unrelated class B, which might in turn invoke a method of class A. The implementation of the Java virtual machine is responsible for taking care of synchronization and recursive initialization by using the following procedure. It assumes that the Class object has already been verified and prepared, and that the Class object contains state that indicates one of four situations:

クラス又はインタフェースの初期化の手続きは,次のとおりとする。
The procedure for initializing a class or interface is then as follows:

  1. 初期化するクラス又はインタフェースを表すオブジェクトClassを同期(14.18)する。これは,現在のスレッドが,そのオブジェクトに対するロックを獲得できるまで待つことを含む(17.13)
    Synchronize (§14.18) on the Class object that represents the class or interface to be initialized. This involves waiting until the current thread can obtain the lock for that object (§17.13).
  2. ある他のスレッドによってそのクラス又はインタフェースの初期化が進行中の場合,(一時的にロックを解除する)このオブジェクトClass上でwaitする(待つ)。現在のスレッドがwaitから目覚めた場合は,この段階を繰り返す。
    If initialization is in progress for the class or interface by some other thread, then wait on this Class object (which temporarily releases the lock). When the current thread awakens from the wait, repeat this step.
  3. 現在のスレッドによってそのクラス又はインタフェースに対する初期化が進行中の場合,これは,初期化に対する再帰的な要求でなければならない。そのオブジェクトClassのロックを解除し,正常に終了する。
    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 the Class object and complete normally.
  4. そのクラス又はインタフェースが既に初期化されている場合,それ以上の動作は必要ではない。そのオブジェクトClassのロックを解除し,正常に終了する。
    If the class or interface has already been initialized, then no further action is required. Release the lock on the Class object and complete normally.
  5. そのオブジェクトClassがエラー状態にある場合,初期化は可能ではない。そのオブジェクトClassのロックを解除し,NoClassDefFoundErrorを投げる。
    If the Class object is in an erroneous state, then initialization is not possible. Release the lock on the Class object and throw a NoClassDefFoundError.
  6. そうでなければ,そのオブジェクトClassの初期化が現在のスレッドで進行中であるという事実を記録し,オブジェクトClassのロックを解除する。
    Otherwise, record the fact that initialization of the Class object is now in progress by the current thread and release the lock on the Class object.
  7. 次に,そのオブジェクトClassが,インタフェースでなくクラスを表現し,このクラスの上位クラスをまだ初期化していない場合,その上位クラスに対してこの手続き全体を繰り返し実行する。必要な場合は,最初にその上位クラスを検証し準備する。上位クラスの初期化が投げられた例外のために中途完了した場合は,オブジェクトClassをロックし,それにエラーとラベル付けし,すべての待機しているスレッドに通知し,ロックを解除し,それからその上位クラスの初期化から結果として生じるものと同じ例外を投げる。
    Next, if the Class object represents a class rather than an interface, and the superclass of this class has not yet been initialized, then recursively perform this entire procedure for the superclass. If necessary, verify and prepare the superclass first. If the initialization of the superclass completes abruptly because of a thrown exception, then lock this Class object, label it erroneous, notify all waiting threads, release the lock, and complete abruptly, throwing the same exception that resulted from initializing the superclass.
  8. 次に,クラス変数初期化子及びクラスの静的初期化子,又はインタフェースのフィールド初期化子のいづれかを,記述してある順序に,それらが単一ブロックであるものとして実行する。ただし,例外として,値がコンパイル時の定数であるfinalクラス変数及びインタフェースのフィールドは,最初に初期化するものとする(8.3.2.1, 9.3.1及び13.4.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 that final class variables and fields of interfaces whose values are compile-time constants are initialized first (§8.3.2.1, §9.3.1, §13.4.8).
  9. 初期化子の実行が正常に完了した場合は,オブジェクトClassをロックし,それを完全に初期化されたとラベル付けし,すべての待機しているスレッドに通知し,ロックを解除し,正常にこの手続きを終了する。
    If the execution of the initializers completes normally, then lock this Class object, label it fully initialized, notify all waiting threads, release the lock, and complete this procedure normally.
  10. そうでない場合は,初期化子は,ある例外 E を投げることによって中途完了していなければならない。E のクラスがError又はその下位クラスの一つでない場合,クラスExceptionInInitializerErrorの新しいインスタンスを,実引数として E を伴って生成し,次の段階では E の代わりにこのオブジェクトを使用する。しかし,OutOfMemoryErrorが発生したために,ExceptionInInitializerErrorの新しいインスタンスが生成できない場合には,その代わりに,次の段階で E の代わりにオブジェクトOutOfMemoryErrorを使用する。
    Otherwise, the initializers must have completed abruptly by throwing some exception E. If the class of E is not Error or one of its subclasses, then create a new instance of the class ExceptionInInitializerError, with E as the argument, and use this object in place of E in the following step. But if a new instance of ExceptionInInitializerError cannot be created because an OutOfMemoryError occurs, then instead use an OutOfMemoryError object in place of E in the following step.
  11. オブジェクトClassをロックし,それにエラーとラベル付けし,すべての待機しているスレッドに通知し,ロックを解除し,理由 E 又は以前の決定したとおりに置き換えた理由を付けて,この手続きを中途完了する。
    Lock the Class 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.

初期の実装の中には,その欠陥のために,ここで示すとおりにExceptionInInitializerErrorを引き起こすのではなく,初期化中の例外を無視するものもあった。

(Due to a flaw in some early implementations, a exception during class initialization was ignored, rather than causing an ExceptionInInitializerError as described here.)

12.4.3 初期化: コード生成との関係
Initialization: Implications for Code Generation

コード生成器は,クラス又はインタフェースの初期化可能な場所を,前述した初期化手続きの呼出しを挿入することによって,保持する必要がある。この初期化手続きが正常に完了し,オブジェクトClassを完全に初期化し使用の準備ができている場合には,初期化手続きの呼出しはもはや不要となる。そこで,例えば,パッチによってそれを解除したり,コードを再生成したりすることによって,コードから削除してもよい。
Code generators need to preserve the points of possible initialization of a class or interface, inserting an invocation of the initialization procedure just described. If this initialization procedure completes normally and the Class object is fully initialized and ready for use, then the invocation of the initialization procedure is no longer necessary and it may be eliminated from the code-for example, by patching it out or otherwise regenerating the code.

関係する型のグループに対する初期化の順序が決定できる場合,コンパイル時の解析によって,生成されたコードからはある型が初期化済みかどうかの多くの検査を除去してもよいことがある。ただし,それらの解析は,並行処理のこと,及び初期化コードが非制限という事実を,十分に考慮しなければならない。

Compile-time analysis may, in some cases, be able to eliminate many of the checks that a type has been initialized from the generated code, if an initialization order for a group of related types can be determined. Such analysis must, however, fully account for concurrency and for the fact that initialization code is unrestricted.

12.5 新しいクラスインスタンスの生成
Creation of New Class Instances

新しいクラスインスタンスは,クラスインスタンス生成式(15.9)がクラスのインスタンス化を引き起こした場合に,明示的に生成される。
A new class instance is explicitly created when evaluation of a class instance creation expression (§15.9) causes a class to be instantiated.

新しいクラスインスタンスは,次の状況において暗黙的に生成されてもよい。

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.

新しいクラスインスタンスが生成される場合はいつでも,隠ぺいされてもよいすべてのインスタンス変数を含む,そのクラス型で宣言されるすべてのインスタンス変数及びそのクラス型のそれぞれの上位クラスで宣言されるすべてのインスタンス変数に対して,十分な大きさのメモリ空間を割り当てられる(8.3)。そのオブジェクトにメモリを割り当てるのに十分な領域がない場合,クラスインスタンスの生成は,OutOfMemoryErrorで中途完了する。そうでない場合は,その新しいオブジェクトにおけるすべてのインスタンス変数は,上位クラスで宣言されたものを含み,それらのデフォルト値に初期化される(4.5.5)

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 (§8.3). If there is not sufficient space available to allocate memory for the object, then creation of the class instance completes abruptly with an OutOfMemoryError. Otherwise, all the instance variables in the new object, including those declared in superclasses, are initialized to their default values (§4.5.5).

新しく生成したオブジェクトへの参照を結果として返す前に,新しいオブジェクトを初期化するために,指定したコンストラクタを,次の手続きを使用して処理する。

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. このコンストラクタが,(thisを使用した)同じクラスの他のコンストラクタの明示的なコンストラクタ呼出しで始まる場合,実引数を評価し,ここに示すのと同じ五つの手順を使用してそのコンストラクタを再帰的に処理する。そのコンストラクタ呼出しが中途完了した場合,この手続きは,同じ理由で中途完了する。そうでない場合は,手順5に移って継続する。
    If this constructor begins with an explicit constructor invocation of another constructor in the same class (using this), then evaluate the arguments and process that constructor invocation recursively using these same five steps. If that constructor invocation completes abruptly, then this procedure completes abruptly for the same reason; otherwise, continue with step 5.
  3. このコンストラクタが,(thisを使用した)同じクラスの他のコンストラクタの明示的なコンストラクタ呼出しで始まらない場合。このコンストラクタが,Object以外のクラスに対するものである場合,このコンストラクタは,(superを使用した)上位クラスのコンストラクタの明示的又は暗黙的な呼出しで開始する。実引数を評価し,ここに示すのと同じ五つの手順を使用してその上位クラスのコンストラクタ呼出しを再帰的に処理する。そのコンストラクタ呼出しが中途完了した場合,この手続きは,同じ理由で中途完了する。そうでない場合は,手順4に移って継続する。
    This constructor does not begin with an explicit constructor invocation of another constructor in the same class (using this). If this constructor is for a class other than Object, then this constructor will begin with an explicit or implicit invocation of a superclass constructor (using super). Evaluate the arguments and process that superclass constructor invocation recursively using these same five steps. If that constructor invocation completes abruptly, then this procedure completes abruptly for the same reason. Otherwise, continue with step 4.
  4. このクラスに対するインスタンス初期化子及びインスタンス変数初期化子を実行し,そのクラスのソースコードにおいて,字句的に出現する左から右の順番で,インスタンス変数初期化子の値を対応するインスタンス変数に代入する。これらの初期化子のいずれかの実行が例外となった場合,それ以降の初期化子は処理されず,この手続きは,同じ例外で中途完了する。そうでない場合は,手順5に移って継続する。(初期の実装では,そのフィールドの初期化子の式が,そのフィールドの型に対するデフォルトの初期値と等しい値をもつ定数式であった場合,コンパイラがそのフィールドを初期化するためのコードを不当に省略していたものがあった。)
    Execute the instance initializers and instance variable initializers for this class, assigning the values of instance variable initializers to the corresponding instance variables, in the left-to-right order in which they appear textually in the source code for the class. If execution of any of these initializers results in an exception, then no further initializers are processed and this procedure completes abruptly with that same exception. Otherwise, continue with step 5. (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.)
  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.
    次に例を示す。
    In the example:

class Point {
	int x, y;
	Point() { x = 1; y = 1; }
}
class ColoredPoint extends Point {
	int color = 0xFF00FF;
}
class Test {
	public static void main(String[] args) {
		ColoredPoint cp = new ColoredPoint();
		System.out.println(cp.color);
	}
}
ColoredPointの新しいインスタンスを生成する。フィールドxy及びcolorを保持するために,最初に新しいColoredPointに対してメモリを割り当てる。これらのすべてのフィールドを,それらのデフォルト値(この場合は,それぞれのフィールドに対して0)に初期化する。次に,コンストラクタColoredPointを実引数なしで最初に呼び出す。ColoredPointは,コンストラクタを宣言していないので,次の形式のデフォルトコンストラクタをJavaコンパイラが自動的に提供する。
a new instance of ColoredPoint is created. First, space is allocated for the new ColoredPoint, to hold the fields x, y, and color. All these fields are then initialized to their default values (in this case, 0 for each field). Next, the ColoredPoint constructor with no arguments is first invoked. Since ColoredPoint declares no constructors, a default constructor of the form:

ColoredPoint() { super(); }
is provided for it automatically by the Java compiler.

それから,このコンストラクタは,コンストラクタPointを実引数なしで呼び出す。コンストラクタPointは,コンストラクタの呼出しで始まらないので,コンパイラが,その上位クラスのコンストラクタの暗黙的な実引数なしの呼出しを提供する。それは,次のとおりに記述したものとする。

This constructor then invokes the Point constructor with no arguments. The Point constructor does not begin with an invocation of a constructor, so the compiler provides an implicit invocation of its superclass constructor of no arguments, as though it had been written:

Point() { super(); x = 1; y = 1; }
したがって,実引数を取らないObjectに対するコンストラクタが呼び出される。
Therefore, the constructor for Object which takes no arguments is invoked.

クラスObjectは,上位クラスをもたないので,再帰はここで終了する。次に,Objectのあらゆるインスタンス初期化子及びインスタンス変数初期化子が呼び出される。さらに,Objectの実引数なしのコンストラクタの本体が実行される。Objectでは,これらコンストラタが宣言されていないので,コンパイラがデフォルトのコンストラクタを供給する。この特別な場合では,次のとおりとなる。

The class Object has no superclass, so the recursion terminates here. Next, any instance initializers, instance variable initializers of Object are invoked. Next, the body of the constructor of Object that takes no arguments is executed. No such constructor is declared in Object, so the compiler supplies a default one, which in this special case is:

Object() { }
このコンストラクタは,何の効果もともなわず実行され返却する。
This constructor executes without effect and returns.

次に,クラスPointのインスタンス変数に対するすべての初期化子が実行される。このとき,x及びyの宣言は,いかなる初期化式も提供しないので,この例のこの段階に対しては,いかなる動作も要求しない。それから,コンストラクタPointの本体が実行され,x1に,y1に設定する。

Next, all initializers for the instance variables of class Point are executed. As it happens, the declarations of x and y do not provide any initialization expressions, so no action is required for this step of the example. Then the body of the Point constructor is executed, setting x to 1 and y to 1.

次に,クラスColoredPointのインスタンス変数に対する初期化子が実行される。この段階では,値0xFF00FFcolorに代入する。最後に,コンストラクタColoredPointの本体の残り(superの呼出しの後の部分)を実行する。本体の残りには文は無いので,それ以上の動作は要求されず,初期化は完了する。

Next, the initializers for the instance variables of class ColoredPoint are executed. This step assigns the value 0xFF00FF to color. Finally, the rest of the body of the ColoredPoint constructor is executed (the part after the invocation of super); there happen to be no statements in the rest of the body, so no further action is required and initialization is complete.

C++と異なり,Javaプログラム言語は,新しいクラスインスタンスの生成中のメソッドディスパッチのための変更規則を指定しない。初期化中のオブジェクトの中で下位クラスで上書きされているメソッドを呼び出す場合,その新しいオブジェクトを完全に初期化する前であっても,これらの上書きしている側のメソッドを使用する。したがって,コンパイル及び実行例は,次のとおりとなる。

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 initialized. Thus, compiling and running the example:

class Super {
	Super() { printThree(); }
	void printThree() { System.out.println("three"); }
}




class Test extends Super {
	int three = (int)Math.PI;	// That is, 3
	public static void main(String[] args) {
		Test t = new Test();
		t.printThree();
	}
	void printThree() { System.out.println(three); }
}
これは,次の出力を得る。
produces the output:

0
3
これは,クラスSuperに対するコンストラクタにおけるprintThreeの呼出しが,クラスSuperprintThreeの定義を呼び出さず,むしろクラスTestにおけるprintThreeの上書き定義を呼び出すことを示している。したがって,このメソッドは,Testのフィールド初期化子が実行される前に動作する。これが,出力の最初の値が0となる理由であって,(この時点では,)Testのフィールドthreeは,デフォルト値に初期化されている。メソッドmainにおけるprintThreeのその後の呼出しは,printThreeの同じ定義を呼び出すが,その時点までには,インスタンス変数threeに対する初期化子が実行されており,そのために値3が出力される。
This shows that the invocation of printThree in the constructor for class Super does not invoke the definition of printThree in class Super, but rather invokes the overriding definition of printThree in class Test. This method therefore runs before the field initializers of Test have been executed, which is why the first value output is 0, the default value to which the field three of Test is initialized. The later invocation of printThree in method main invokes the same definition of printThree, but by that point the initializer for instance variable three has been executed, and so the value 3 is printed.

コンストラクタ宣言の詳細については,8.8を参照すること。

See §8.8 for more details on constructor declarations.

12.6 クラスインスタンスの終了
Finalization of Class Instances

クラスObjectは,finalizeと呼ぶprotectedメソッドをもつ。このメソッドは,他のクラスによって上書きできる。あるオブジェクトに対して呼び出すことができるfinalizeの特定の定義を,そのオブジェクトの 終了化子(finalizer) と呼ぶ。オブジェクトに対する記憶域をガーベジコレクタが再利用する前に,Java仮想計算機は,そのオブジェクトの終了化子を呼び出す。
The class Object has a protected method called finalize; this method can be overridden by other classes. The particular definition of finalize that can be invoked for an object is called the finalizer of that object. Before the storage for an object is reclaimed by the garbage collector, the Java virtual machine will invoke the finalizer of that object.

終了化子は,自動記憶域管理機構によって自動的には解放できない資源を解放するための機会を提供する。そのような状況では,あるオブジェクトが使用したメモリを再利用することは,それが保持していた資源を再利用でき ることを保証するものではない。

Finalizers provide a chance to free up resources 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.

Javaプログラム言語は,オブジェクトに対する記憶域を再利用する前に終了化子が動作するという点を除いて,終了化子をどれぐらい早く呼び出すかを規定しない。Javaプログラム言語は,どのスレッドがある特定のオブジェクトに対して終了化子を呼び出すかをも規定しない。しかし,終了化子を呼び出すスレッドが,終了化子を呼び出したときに,利用者に見えるどのような同期ロックも保持していないことは保証する。終了化実行中に捕捉されない例外が投げられた場合,その例外は無視され,そのオブジェクトの終了化が終了する。

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. Also, the language does not specify which thread will invoke the finalizer for any given object. It is guaranteed, however, that the thread that invokes the finalizer will not be holding any user-visible synchronization locks when the finalizer is invoked. If an uncaught exception is thrown during the finalization, the exception is ignored and finalization of that object terminates.

クラスObjectで宣言されているメソッドfinalizeは,いかなる動作も実行しない。

The finalize method declared in class Object takes no action.

クラスObjectがメソッドfinalizeを宣言しているという事実は,任意のクラスに対するメソッドfinalizeが,その上位クラスに対するメソッドfinalizeを常に呼び出すことができるということを意味する。これを行うことは,通常,良い習慣である。コンストラクタと異なり,終了化子は,上位クラスに対する終了化子を自動的に呼び出さない。それらの呼出しは,明示的に記述しなければならない。

The fact that class Object declares a finalize method means that the finalize method for any class can always invoke the finalize 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.)

実行効率のために,処理系は,クラスObjectのメソッドfinalizeを上書きしないクラスを覚えておいてもよいが,次に示すとおりの自明な方法でそれを上書きしてもよい。

For efficiency, an implementation may keep track of classes that do not override the finalize method of class Object, or override it in a trivial way, such as:

protected void finalize() throws Throwable {
	super.finalize();
}
処理系は,12.6.1で示すとおりに,上書きされない終了化子をもつオブジェクトを扱い,より効率的にそれらを終了化することを推奨する。
We encourage implementations to treat such objects as having a finalizer that is not overridden, and to finalize them more efficiently, as described in §12.6.1.

終了化子は,他のメソッドと同じように明示的に呼び出してもよい。

A finalizer may be invoked explicitly, just like any other method.

パッケージjava.lang.refは,ガーベジコレクション及び終了化と相互作用する弱参照(weak reference)を記述している。Javaと特別な相互作用をもつAPIを用いる場合,実装者は,java.lang.ref APIが課す要件を認識しなければならない。この規定は,弱参照について示さない。詳細に関してはAPIの文書を参照すること。

The package java.lang.ref describes weak references, which interact with garbage collection and finalization. As with any API that has special interactions with the language, implementors must be cognizant of any requirements imposed by the java.lang.ref API. This specification does not discuss weak references in any way. Readers are referred to the API documentation for details.

12.6.1 終了化子の実装
Implementing Finalization

すべてのオブジェクトは,二つの属性によって分類できる。すなわち,オブジェクトは,到達可能(reachable)終了化子到達可能(finalizer-reachable) 又は 到達不能(unreachable)のどれか,及び 未終了化(unfinalized)終了化可能(finalizable) 又は 終了化(finalized) のどれかで分類できる。
Every object can be characterized by two attributes: it may be reachable, finalizer-reachable, or unreachable, and it may also be unfinalized, finalizable, or finalized.

到達可能(reachable) オブジェクトとは,あらゆるライブスレッドからの潜在的に継続する計算でアクセスできるあらゆるオブジェクトとする。プログラムの最適化変換は,到達可能なオブジェクトの数を,単純に到達可能と考えられるオブジェクトの数よりも少ない数に削減するように設計できる。例えば,コンパイラ又はコード生成器は,それらオブジェクトに対する記憶域を潜在的にすぐに再利用可能とするために,もはや使用されない変数又は仮引数を,nullに設定することを選択してもよい。終了化子到達可能(finalizer-reachable) オブジェクトとは,参照のある連鎖を通じて,ある終了化可能オブジェクトからは到達できるが,いかなるライブスレッドからも到達できないものとする。到達不能(unreachable) オブジェクトとは,いづれの方法でも到達できないものとする。

A reachable object is any object that can be accessed in any potential continuing computation from any live thread. Optimizing transformations of a program can be designed that reduce the number of objects that are reachable to be less than those which would naively be considered reachable. For example, a compiler or code generator may choose to set a variable or parameter that will no longer be used to null to cause the storage for such an object to be potentially reclaimable sooner. A finalizer-reachable object can be reached from some finalizable object through some chain of references, but not from any live thread. An unreachable object cannot be reached by either means.

未終了化(unfinalized) オブジェクトとは,終了化子が一度も自動的に呼び出されていないものとする。終了化(finalized) オブジェクトとは,終了化子が自動的に呼び出されたものとする。終了化可能(finalizable) オブジェクトとは,終了化子が一度も自動的に呼び出されていないが,Java仮想計算機が,終了化子を最終的には自動的に呼び出すかもしれないものとする。

An unfinalized object has never had its finalizer automatically invoked; a finalized object has had its finalizer automatically invoked. A finalizable object has never had its finalizer automatically invoked, but the Java virtual machine may eventually automatically invoke its finalizer.

オブジェクトのライフサイクルは,次の遷移図に従うものとする。ここで,"終了化子到達可能"は,"f-reachable"と短縮表記している。

The life cycle of an object obeys the following transition diagram, where we abbreviate "finalizer-reachable" as "f-reachable":

オブジェクトを最初に生成したとき(A),それは到達可能及び未終了化とする。

When an object is first created (A), it is reachable and unfinalized.

あるオブジェクトへの参照がプログラム実行中に廃棄されるとき,到達可能であったオブジェクトは,終了化子到達可能(B,C又はD)又は到達不能(E又はF)になってよい。終了化子到達可能オブジェクトは,直接的には到達不能にならないことに注意すること。以降に示すとおり,それは,そこから到達可能な終了化子を呼び出すときに到達可能となる。

As references to an object are discarded during program execution, an object that was reachable may become finalizer-reachable (B, C, D) or unreachable (E, F). (Note that a finalizer-reachable object never becomes unreachable directly; it becomes reachable when the finalizer from which it can be reached is invoked, as explained below.)

Java仮想計算機が,未終了化オブジェクトが終了化子到達可能又は到達不能になったことを検出した場合,そのオブジェクトを終了化可能(G又はH)とラベル表示してもよい。さらに,そのオブジェクトが到達不能であった場合,それは終了化子到達可能になる(H)。

If the Java virtual machine detects that an unfinalized object has become finalizer-reachable or unreachable, it may label the object finalizable (G, H); moreover, if the object was unreachable, it becomes finalizer-reachable (H).

Java仮想計算機が,終了化オブジェクトが到達不能になったことを検出した場合,そのオブジェクトは再び到達可能にはならないので,そのオブジェクトが占有している記憶域を再利用してもよい(I)。

If the Java virtual machine detects that a finalized object has become unreachable, it may reclaim the storage occupied by the object because the object will never again become reachable (I).

任意の時点で,Java仮想計算機は,終了化可能なオブジェクトを取り出し,それに終了化とラベル表示を行い,それからいずれかのスレッドにおけるそのメソッドfinalizeを呼び出してもよい。これによって,そのオブジェクトは終了化及び到達可能(J又はK)になり,さらにそれは,終了化子到達可能であった他のオブジェクトを,再び到達可能にしてもよい(K,M又はN)。

At any time, a Java virtual machine may take any finalizable object, label it finalized, and then invoke its finalize method in some thread. This causes the object to become finalized and reachable (J, K), and it also may cause other objects that were finalizer-reachable to become reachable again (L, M, N).

終了化可能オブジェクトは,到達不能とはならない。終了化子が最終的に呼び出されるので,到達可能となる。その上で,その終了化子を実行しているスレッドは,そのオブジェクトに対するアクセスを,this (15.8.3)としてもつ。このように,オブジェクトに対して,八つの可能な状態だけが実際には存在する。

A finalizable object cannot also be unreachable; it can be reached because its finalizer may eventually be invoked, whereupon the thread running the finalizer will have access to the object, as this (§15.8.3). Thus, there are actually only eight possible states for an object.

オブジェクトを終了した後,自動記憶域管理が到達可能でないと決定するまでは,それ以上の動作は実行されない。オブジェクトが 未終了化(unfinalized) 状態から 終了化可能(finalizable) 状態を経由して 終了化(finalized) 状態に進行する方式なので,そのオブジェクトが終了化した後に再び到達可能になったとしても,それぞれのオブジェクトに対してメソッドfinalizeがJava仮想計算機によって2度以上自動的に呼び出されることはない。

After an object has been finalized, no further action is taken until the automatic storage management determines that it is unreachable. Because of the way that an object progresses from the unfinalized state through the finalizable state to the finalized state, the finalize method is never automatically invoked more than once by a Java virtual machine for each object, even if the object is again made reachable after it has been finalized.

終了化子の明示的な呼出しは,オブジェクトの現在の状態を無視し,オブジェクトの状態を未終了化又は終了化可能から終了化に変更することはない。

Explicit invocation of a finalizer ignores the current state of the object and does not change the state of the object from unfinalized or finalizable to finalized.

あるクラスが,クラスObjectのメソッドfinalizeを上書きしない場合(又は前述したとおり,自明な方法だけで上書きする場合)であって,それらのクラスのインスタンスが到達不能になる場合,それらが到達不能になったという(条件の)2番目の決定を待たずに,速やかに廃棄してもよい。この戦略は,遷移図の中に破線の矢印(O)で示している。

If a class does not override method finalize of class Object (or overrides it in only a trivial way, as described above), then if instances of such a class become unreachable, they may be discarded immediately rather than made to await a second determination that they have become unreachable. This strategy is indicated by the dashed arrow (O) in the transition diagram.

したがって,メソッドfinalizeの設計は簡潔さを保ち,防衛的にプログラムするのがよい。これによって,すべての場合で動作するようになるだろう。

Therefore, we recommend that the design of finalize methods be kept simple and that they be programmed defensively, so that they will work in all cases.

12.6.2 終了化子の呼出しの非順序性
Finalizer Invocations are Not Ordered

Javaプログラム言語は,終了化メソッドの呼出しについて,いかなる順序性も強制しない。終了化子は,任意の順序で呼び出してよいし,並行実行的に呼び出してもよい。
The Java programming language imposes no ordering on finalize 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 (or finalizer-reachable), 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.

すべてのオブジェクトが到達不能になる場合,それらオブジェクトの集合に対して,終了化子的なメソッドの集合を指定した順序で呼び出すクラスを実装することは簡単といえる。

It is straightforward to implement a class that will cause a set of finalizer-like methods to be invoked in a specified order for a set of objects when all the objects become unreachable. Defining such a class is left as an exercise for the reader.

12.7 クラス及びインタフェースのアンロード
Unloading of Classes and Interfaces

Javaプログラム言語の処理系は,クラスを アンロード(unloaded) してもよい。クラス又はインタフェースは,それを定義しているクラスローダが12.6で示されるとおりにガーベジコレクションによって再利用される場合に限り,アンロードしてもよい。ブートストラップローダによってロードされるクラス及びインタフェースは,アンロードしてはならない。
An implementation of the Java programming language may unload classes. A class or interface may be unloaded if and only if its defining class loader may be reclaimed by the garbage collector as discussed in §12.6. Classes and interfaces loaded by the bootstrap loader may not be unloaded.

次に,前段落で与えられた規則に対する理由を示す。

Here is the rationale for the rule given in the previous paragraph:

クラスのアンロードは,メモリ使用の削減を助ける最適化とする。プログラムのセマンティクスは,システムがクラスのアンロードなどの最適化を実装するかどうか,及びどのように実装するか,に依存しないほうがよい。依存する場合には,プログラムの移植性を損ねる可能性がある。結果として,クラス又はインタフェースがアンロードされたかどうかは,プログラムに透過的であることが望ましい。

Class unloading is an optimization that helps reduce memory use. Obviously, the semantics of a program should not depend on whether and how a system chooses to implement an optimization such as class unloading. To do otherwise would compromise the portability of programs. Consequently, whether a class or interface has been unloaded or not should be transparent to a program.

しかし,クラス又はインタフェース C が,それを定義するローダが潜在的に到達可能な間にアンロードされる場合は,C が再ロードされるかもしれない。このことが発生しないと確実にすることはできない。クラスが現在ロードされている他のクラスによって参照されていない場合でさえも、まだロードされていないクラス又はインタフェース D によって参照されるかもしれない。DC を定義するローダによってロードされる場合は,その実行は,C の再ロードを生じるかもしれない。

However, if a class or interface C was unloaded while its defining loader was potentially reachable, then C might be reloaded. One could never ensure that this would not happen. Even if the class was not referenced by any other currently loaded class, it might be referenced by some class or interface, D, that had not yet been loaded. When D is loaded by C's defining loader, its execution might cause reloading of C.

例えば,クラスが次をもつ場合には,再ロードは透過的でないかもしれない。

Reloading may not be transparent if, for example, the class has:

さらに,Class オブジェクトのハッシュ値は,その識別性に依存する。したがって,一般には,クラス又はインタフェースを完全に透過的な方法で再ロードすることは不可能である。
Furthermore the hash value of the Class object is dependent on its identity. Therefore it is, in general, impossible to reload a class or interface in a completely transparent manner.

ローダが潜在的に到達可能であるクラス又はインタフェースのアンロードは再ロードを引き起こさず,再ロードは透過的ではないが,アンロードは透過的でなければならない,といったことを保証できないので,そのローダが潜在的に到達可能である間は,クラス又はインタフェースをアンロードしてはならないことになる。同様の論理を使用して,ブートストラップローダがロードするクラス及びインタフェースはアンロードできないということを導き出せる。

Since we can never guarantee that unloading a class or interface whose loader is potentially reachable will not cause reloading, and reloading is never transparent, but unloading must be transparent, it follows that one must not unload a class or interface while its loader is potentially reachable. A similar line of reasoning can be used to deduce that classes and interfaces loaded by the bootstrap loader can never be unloaded.

クラス C を定義するクラスローダを再利用可能な場合,そのクラスをアンロードすることが安全な理由も議論しなければならない。その定義ローダを再利用可能な場合には,そのローダへのライブ参照(ただし,これには,ライブではないが,終了化子によって復活するかもしれない参照が含まれる。)は存在できない。このことは,そのローダが定義する C を含むクラスへの,それらクラスのインスタンス又はコードのいずれかからのライブ参照が存在できない場合にだけ,成立可能となる。

One must also argue why it is safe to unload a class C if its defining class loader can be reclaimed. If the defining loader can be reclaimed, then there can never be any live references to it (this includes references that are not live, but might be resurrected by finalizers). This, in turn, can only be true if there are can never be any live references to any of the classes defined by that loader, including C, either from their instances or from code.

クラスのアンロードは,多くのクラスをロードし,多少時間が経った後にこれらクラスの大部分の使用を中止するアプリケーションに対してだけ重要な最適化になる。こうしたアプリケーションの主要な例はウェブブラウザだが,他にも存在する。これらアプリケーションの特徴は,クラスローダの明示的な使用を通してクラスを管理することにある。結果として,先に示した方針は,これらに対して正しく機能する。

Class unloading is an optimization that is only significant for applications that load large numbers of classes and that stop using most of those classes after some time. A prime example of such an application is a web browser, but there are others. A characteristic of such applications is that they manage classes through explicit use of class loaders. As a result, the policy outlined above works well for them.

厳密に言えば,クラスのアンロードの問題をこの規定で示すことは重要ではない。これは,クラスのアンロードが単に最適化であることによる。しかし,この問題は非常に微妙な問題なので,明確化のためにここに示した。

Strictly speaking, it is not essential that the issue of class unloading be discussed by this specification, as class unloading is merely an optimization. However, the issue is very subtle, and so it is mentioned here by way of clarification.

12.8 プログラムの抜け出し
Program Exit

プログラムは,すべての活動を終了し,次の二つのうちの一つが発生した場合に 抜け出す (exit)
A program terminates all its activity and exits when one of two things happens:

目次 | | | 索引 Java言語規定
第2版