2016-11-29 4 views
8

これは純粋に概念的な質問です。1つのJavaクラスで使用されるラムダの最大数はいくらですか?

Java 8のLambdaは、invokedynamicを使用して呼び出されるメソッドに変換されます。

1つのクラスが持つことができるメソッドの最大数にJVMの制限がある場合、1つのクラスで使用されるラムダの最大数もJVMによって厳密に制限されますか?

この質問はこれとほとんど同じですか? What is the maximum number of methods a Java class can have?

+4

"Java 8のLambdaは、' invokedynamic'を使って呼び出されるメソッドに変換されます。 "---これは間違っています。 lambda_creation_サイトだけが 'invokedynamic'を持っており、ランタイムは各サイトで作成戦略を選択できます。 Lambas自体は、lambdaメソッドで必要なインタフェースを実装するアドホッククラスのインスタンスに変換されます。 –

+2

OTOH、いくつかの種類のラムダは、宣言するクラスにメソッドを追加します。しかし、その制限はGoogleに簡単です。 http://stackoverflow.com/questions/4342072/what-is-the-maximum-number-of-methods-a-java-class-can-have –

+2

Javaクラスのフォーマットには64Kの制限があり、これにより制限されます1つのクラスで参照できるラムダ(および定数/メソッド呼び出し)の数。 –

答えて

7

Java言語仕様には制限がありません。そのため、技術的な制限があります。この仕様では、コンパイルされた特定のフォームも必須ではないため、技術的な限界があいまいです。

ラムダ式は、ラムダ式の本体をホストするクラスファイルのメソッドにコンパイルされますが、これは厳密には必須ではありません。最も顕著なのは、foo -> bar(foo)という形式の簡単な式は、メソッド参照のようにコンパイルされる可能性があります。さらに、同じラムダ式を同じメソッドを使用してコンパイルすることもできます。これは現在発生していない最適化であり、デバッグも難しくなりますが、原則として許可されます。

また、スマートコンパイラは、限界に近づいている可能性が低いと判断した場合、ラムダボディをホストする補助クラスの生成を開始できます。

現在の直接的な実装では、メソッドの最大数、つまり65535が可能なラムダ式の最大数に影響しますが、これは65535ラムダ式を作成できることを意味しません。

たとえば、機能インタフェースのインスタンスを作成するラムダ式を含む少なくとも1つのメソッド(ソースコード)が必要です。作成サイトの最小命令サイズは、invokedynamic命令が5バイト1を持つ唯一の命令です。メソッドの最大コードサイズは65535であり、return命令の場合は少なくとも1つ必要です。したがって、1つのメソッドで最大で65534/5 == 13106ラムダ式が存在する可能性があります。したがって、より多くを作成しようとすると、異なるメソッドに配置する必要がありますラムダ式で利用可能なメソッドの一覧です。ネストされたラムダ式を使用すると、x -> y -> z,but even nesting has practical limitsのように回避できます。

現在のコンパイラは、各合成メソッドに固有の名前を生成する命名方式を使用するため、個々の定数プールエントリが必要です。だから独自の実装メソッドを持つと、各ラムダ作成サイトには、名前を参照する名前&の型、型名&を参照する "MethodRef"、および(常に同じ)宣言クラス、メソッドハンドル"MethodRef"とメソッドハンドルを参照するinvokedynamicエントリを参照してください。これにより、ラムダ式ごとに合計5つの定数プールエントリが作成され、定数プールは65534エントリに制限され、他の目的のためにいくつかのエントリが必要なため、計算は65500/5であるため、現在のコンパイラ実装ではラムダ式は13,100です。彼らはすべて同じ署名を持っていると仮定します...

javac(1.8u111)での練習テストでは、同じシグネチャの13,098ラムダ式を使用してクラスファイルをコンパイルすることができました。 「あまりにも多くの定数」が現れました。そのテストクラスでは、ラムダ式を2つのコンストラクタに入れます。少なくとも1つのコンストラクタが存在しなければならず、両方とも名前のエントリを共有できるためです。私は、標準のコンパイラではそれ以上のことはできないと思う。


あなたが命名方式による制限を解除したい場合、あなたはまだ、各メソッドが識別可能でなければならないという規則を遵守しなければならないので、それは他からの、少なくともいずれかで、名前や署名によって異なっていなければなりませんメソッド。あなたは理論上の最大値に到達しようとした場合、あなたはメートルn×m明確な方法を可能にするために明確なシグネチャを持つNの異なるメソッド名を結合する必要がありますので、65535個の方法は、少なくとも256名エントリおよび256の署名エントリが必要になります。固有の名前は&で、ラムダ式ごとに4つのエントリが必要になり、16,247のラムダ式が可能になります。これらは65535よりはるかに小さいので、12832の名前と128の署名を組み合わせ、作成サイトに対してより多くのエントリを持つ、つまり16311個の可能なラムダ式を持つ、より小さな名前の&タイプの組み合わせに対処することができます。署名文字列をメソッド名として悪用した場合(署名に参照型が含まれていない限り、バイトコードレベルで動作します)。

(かなり)多くの場合、ラムダ式ごとに異なるメソッドの生成を停止する必要があります。


¹有効なバイトコードを作成します。ソースコードレベルでは、ラムダ式はステートメントではありません。変数への代入が必要です。

関連する問題