私はJavaバイトコードから取得したいくつかの分解されたコードを見ています。私は次のようにいくつかの宣言を見ます:
.method static synthetic access$0()Lcom/package/Sample;
synthetic
またはのaccess$0
意味がわかりません。誰かが私がこの部分を理解するのを手伝ってくれますか?
私はJavaバイトコードから取得したいくつかの分解されたコードを見ています。私は次のようにいくつかの宣言を見ます:
.method static synthetic access$0()Lcom/package/Sample;
synthetic
またはのaccess$0
意味がわかりません。誰かが私がこの部分を理解するのを手伝ってくれますか?
Java言語では、内部クラスはそれを囲むクラスのプライベートメンバーにアクセスできます。ただし、Javaバイトコードでは、内部クラスの概念は存在せず、プライベートメンバーにはアクセスできません。これを回避するために、コンパイラは外部クラスに合成アクセサメソッドを作成します。それがあなたがここで見ているものだと思います。access$0
単にメソッドの名前です。どちらかといえば、私にはわかりませんsynthetic
。カプセル化を確実にするために、他のコンパイラからメソッドを隠すだけかもしれません。
ローカル内部クラスをブロックのローカル変数または参照型パラメーターにリンクするコンパイラー作成フィールド。
The JavaTM Virtual Machine Specification (§4.7.6)
またはJavaの合成クラスも参照してください 。
assert
ステートメントJDK1.8のケーススタディ
このassert
ステートメントは、static synthetic
OracleJDK1.8.0_45でフィールドを生成する構成の例です。
public class Assert {
public static void main(String[] args) {
assert System.currentTimeMillis() == 0L;
}
}
基本的にコンパイルされます:
public class Assert {
// This field is synthetic.
static final boolean $assertionsDisabled =
!Assert.class.desiredAssertionStatus();
public static void main(String[] args) {
if (!$assertionsDisabled) {
if (System.currentTimeMillis() != 0L) {
throw new AssertionError();
}
}
}
}
これは次の方法で確認できます。
javac Assert.java
javap -c -constants -private -verbose Assert.class
を含む:
static final boolean $assertionsDisabled;
descriptor: Z
flags: ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC
合成フィールドは、Javaがロード時に1回だけ呼び出す必要があるように生成されAssert.class.desiredAssertionStatus()
、結果をそこにキャッシュします。
詳細な説明については、https://stackoverflow.com/a/29439538/895245も参照してください。
この合成フィールドは、定義する他のフィールドとの名前の競合を生成する可能性があることに注意してください。たとえば、以下はOracleJDK1.8.0_45でのコンパイルに失敗します。
public class Assert {
static final boolean $assertionsDisabled = false;
public static void main(String[] args) {
assert System.currentTimeMillis() == 0L;
}
}
識別子にドルを使用しないという命名規則が「防止」する唯一のことです。参照:変数名にドル記号($)を使用する必要があるのはいつですか?
ボーナス:
static final int $assertionsDisabled = 0;
Javaとは異なり、バイトコードでは同じ名前で異なるタイプの複数のフィールドが許可されるため、機能します。同じ名前で異なるタイプの変数