Java クラスファイルの構成 その3


# 属性

クラスファイル、メソッド、フィールド、Code 属性は属性という形で様々な情報を持っています。
属性は以下の様な構造となっています。

```
attribute_info {
  tag           // 2 byte
  length        // 4 byte
  data          // length byte
}
```

tag は属性名を表す文字列定数の定数プール上でのインデックスです。
length はそれに続く data の部分の長さを示します。
data の内容をどう解釈するかは属性名によって変化します。
クラスファイルを解釈するソフトウェア (javac や jvm) は自身の知らない属性名の属性は無視します。
Java 仮想マシン仕様には以下に挙げる 23 種類の属性が定義されており、それぞれ出現する場所が決められています。

| 属性名 | クラスファイル | メソッド | フィールド | Code 属性 | 
|-------------------------------------|:---:|:---:|:---:|:---:|
|RuntimeVisibleTypeAnnotations        | ○   | ○   | ○   | ○   |
|RuntimeInvisibleTypeAnnotations      | ○   | ○   | ○   | ○   |
|RuntimeVisibleAnnotations            | ○   | ○   | ○   |     |
|RuntimeInvisibleAnnotations          | ○   | ○   | ○   |     |
|Synthetic                            | ○   | ○   | ○   |     |
|Deprecated                           | ○   | ○   | ○   |     |
|Signature                            | ○   | ○   | ○   |     |
|SourceFile                           | ○   |     |     |     |
|InnerClasses                         | ○   |     |     |     |
|EnclosingMethod                      | ○   |     |     |     |
|SourceDebugExtension                 | ○   |     |     |     |
|BootstrapMethods                     | ○   |     |     |     |
|RuntimeVisibleParameterAnnotations   |     | ○   |     |     |
|RuntimeInvisibleParameterAnnotations |     | ○   |     |     |
|AnnotationDefault                    |     | ○   |     |     |
|Code                                 |     | ○   |     |     |
|Exceptions                           |     | ○   |     |     |
|MethodParameters                     |     | ○   |     |     |
|ConstantValue                        |     |     | ○   |     |
|LineNumberTable                      |     |     |     | ○   |
|LocalVariableTable                   |     |     |     | ○   |
|LocalVariableTypeTable               |     |     |     | ○   |
|StackMapTable                        |     |     |     | ○   |

例えば、Signature 属性はジェネリクスを含む型情報を表現する属性でクラスファイル、メソッド、及びフィールドに付与されます。
Code 属性はメソッドボディのプログラムの内容を表現する属性で、メソッドに付与されます。

まずは説明が楽な属性を幾つか紹介します。

## Synthetic 属性

この属性はクラスファイル・メソッド・フィールドに付与される属性で、そのクラスファイル・メソッド・フィールドがソースコードを持たない、コンパイラ等に自動的に生成されたものであることを表します。
Synthetic 属性は data 部分を持ちません。

## Deprecated 属性

この属性はクラスファイル・メソッド・フィールドに付与される属性で、そのクラスファイル・メソッド・フィールドが非推奨であることを表します。
Deprecated 属性は data 部分を持ちません。

## SourceFile 属性

この属性はクラスファイルに付与される属性で、そのクラスファイルのソースファイルを表します。この属性は必須ではなく、主にデバッグに利用されます。
data 部分は 2 バイトで、ソースファイル名を表す文字列定数の定数プール上でのインデックスです。

## SourceDebugExtension 属性

この属性はクラスファイルに付与される属性で、デバッグのための追加の情報を保持します。
この属性は可変長で、data 部分は 拡張 UTF-8 にエンコードされた文字列です。
ただし、この文字列は String クラスのオブジェクトとして表現可能な長さよりも長い可能性があります。

## ConstantValue 属性

この属性はフィールドに付与される属性で、static フィールドの初期値が特定の型の定数である場合にその値を保持するのに用いられます。(そのフィールドが final であることは要求されません)
この初期化は static イニシャライザによる初期化よりも先に行われます。

この属性の data 部分は 2 バイトで、フィールド初期値となる定数値の定数プール上のインデックスです。
フィールドの型が int, short, char, byte, boolean の場合は参照される定数は int 定数です。
また、float, long, double, String の場合はそれぞれ float 定数、long 定数、double 定数、文字列リテラルを表現する定数(文字列定数ではなく)となります。

## Exceptions 属性

この属性はメソッドに付与される属性で、そのメソッドが投げる可能性のあるチェック例外を表現します。
data 部分は以下の様な構造となっています。

```
exceptions_attribute_data {
  count               // 2 byte
  exceptions          // 2 byte * count個
}
```

exceptions の各エントリはクラスを表現する定数の定数プール上のインデックスです。

メソッドが投げる例外は、ここで指定されたクラス及びそのサブクラスか、RuntimeException, Error 及びそのサブクラスのオブジェクトであるべきです。
しかし、実は JVM はここに書いていないチェック例外を投げることも許しています。
チェック例外を throws 節に書かなければならないというのは Java 言語の制約であり、JVM にはそのような制約はありません。

# あとがき

説明が楽な属性はほとんど終わってしまいました。
ここから先は正直説明がしんどいものばかりです。
ぼちぼちがんばります。

ここに書いた情報は全てJavaの仮想マシン仕様書に書いてあります。
詳しく知りたい方はそちらを読みましょう。