Javaメソッド宣言のパラメーターの最大数


133

Javaのメソッドが持つことができるパラメーターの最大数はいくつですか?なぜですか?

64ビットWindowsシステムでJava 1.8を使用しています。

これに関するStackOverflowのすべての回答は、技術的な制限は理由を指定せずに255パラメータであると述べています。

正確には、静的thisメソッドは255、非静的メソッドは254(この場合は255番目)です。

これはある種の仕様で説明でき、静的に定義されたパラメーターの最大数が許可されているだけだと思いました。

しかし、これはintすべての4バイトタイプでのみ有効でした。longパラメータを使用していくつかのテストを行いましたが、その場合は127個のパラメータしか宣言できませんでした。

Stringパラメータ、試験から推定される許容数Iは、(基準サイズは、Javaで4バイトであるので、それがあってもよい?)255です。

ただし、64ビットシステムを使用しているので、参照サイズは8バイト幅にする必要があります。したがって、Stringパラメーターの場合、longタイプと同様に、最大許容数は127にする必要があります。

この制限はどのように正確に適用されますか?

制限はメソッドのスタックサイズと関係がありますか?

注:これらの多くのパラメーターをメソッドで実際に使用するつもりはありませんが、この質問は正確な動作を明確にすることだけを目的としています。


39
7、読みやすさで狂気になりたくない場合。(私はあなたが実際に求めていることを知っています)。
Adam

14
私は主張するでしょう<= 4。それ以上のものはおそらくオブジェクトにラップされるべきです。
Vivin Paliath

4
なぜこれが興味深い質問なのですか?プログラムを作成していて、この制限に達している場合は、設計が間違っています。なぜこのような実質的に役に立たない質問が非常に多くの賛成票を獲得するのか理解できません。
Jesper、2015年

20
@Jesperは、JVM仕様の知識を問うためです。この質問は、「これを行う方法またはそれを行う方法」を尋ねるものではありません。代わりに、「なぜそれが必要なのか」と質問します... +1興味深い質問Userv
Amit

2
@まさに私が考えていたものを認める。OPはちょうどそれについて興味がありました。
エヴァンCarslake

回答:


110

その制限は、JVM仕様で定義されています。

メソッドパラメータの数は、メソッド記述子の定義(§4.3.3)によって255に制限されています。インスタンスまたはインターフェイスのメソッド呼び出しの場合、制限にはこのための1つの単位が含まれます。

セクション§4.3.3はいくつかの追加情報を提供します:

メソッド記述子は、全長が255以下のメソッドパラメーターを表す場合にのみ有効です。インスタンスまたはインターフェースのメソッド呼び出しの場合、その長さには、この長さが含まれます。

全長は、個々のパラメーターの寄与を合計することによって計算されます。ここで、longまたはdoubleタイプのパラメーターは長さに対して2単位を提供し、他のタイプのパラメーターは1単位を提供します。

あなたの観察は正解でした、ダブルワードプリミティブ(long/ double)には、通常の4バイトの変数と4バイトのオブジェクトインスタンス参照の 2倍のサイズが必要です。

64ビットシステムに関する質問の最後の部分に関して、仕様はパラメータが貢献するユニットの数を定義します。仕様のその部分は、64ビットプラットフォーム準拠する必要があります。64ビットJVMは、255のインスタンスパラメータ(255など)に対応しますStrings)内部オブジェクトのポインタサイズに関係なく。


10
この回答に加えて、64ビットアーキテクチャではスタックも64ビットであることを付け加えておきます。したがって、パラメーター数の制限はスタックサイズによって制限されるため、64ビットスタックでは同じ255個のオブジェクト参照を格納できます。特定の処理longdouble関係なく、システムアーキテクチャのは、スペックの多くの場所で発生し、32ビット時代のレムナントであるように見えます。
セルゲイ

私はその部分だけを編集している最中でした:)そうですね、異なるプラットフォームでもスペックは尊重されなければなりません。
ウンベルトライモンディ2015年

1
ええ、パラメータの数がワードサイズの関数である場合、移植性が損なわれます。同じJavaプログラムを異なるアーキテクチャーで正常にコンパイルすることはできません。
Vivin Paliath

3
可変引数はオブジェクト配列に変換され、パラメーターリストで1回だけ使用でき、最後の位置を占めます。これらすべてを考慮すると、varargsを使用すると、パラメーターの数を254 + Integer.MAX_VALUE(少なくともプログラマーの場合はパラメーターは255のまま)に「拡張」できるため、そのトリックを使用してIntegerを使用できます。 MAX_VALUEオブジェクトパラメータ。
ウンベルトライモンディ2015年

1
@MrTsjolder varargsについては、この回答をご覧ください。
Vivin Paliath

11

JVM仕様のセクション4.3.3には、探している情報があります。

メソッド記述子は、全長が255以下のメソッドパラメータを表す場合にのみ有効です。インスタンスまたはインターフェイスのメソッド呼び出しの場合、その長さには、この長さが含まれます。全長は、個々のパラメーターの寄与を合計することによって計算されます。ここで、 longまたはdoubleタイプの パラメーターは長さに 2単位寄与し、他のタイプのパラメーターは1単位寄与します。

したがって、ホストマシンが32ビットか64ビットかはパラメーターの数に影響を与えないようです。あなたが気づいたら、ドキュメントは「ユニット」に関して語っています。1つの「ユニット」の長さはワードサイズの関数です。パラメータの数がワードサイズに正比例する場合、移植性の問題があります。同じJavaプログラムを異なるアーキテクチャーでコンパイルすることはできません(少なくとも1つのメソッドが、ワードサイズの大きいアーキテクチャーのパラメーターの最大数を使用したと想定)。


10

これに関するニュースレターから興味深い問題を見つけました、http://www.javaspecialists.eu/archive/Issue059.html

クラスごとまたはインターフェイスごとの定数プールは、ClassFile構造体の16ビットのconstant_pool_countフィールドによって65535エントリに制限されています。これは、単一のクラスまたはインターフェースの全体的な複雑さに対する内部制限として機能します。非ネイティブ、非抽象メソッドごとのコードの量は、Code属性のexception_table、LineNumberTable属性、およびLocalVariableTable属性のインデックスのサイズによって65536バイトに制限されます。

メソッドの呼び出し時に作成されるフレームのローカル変数配列内のローカル変数の最大数は、メソッドのコードを提供するCode属性のmax_localsアイテムのサイズによって65535に制限されます。long型とdouble型の値はそれぞれ2つのローカル変数を予約し、max_locals値に2つの単位を与えると見なされるため、これらの型のローカル変数を使用すると、この制限がさらに削減されます。

クラスまたはインターフェースで宣言できるフィールドの数は、ClassFile構造体のfields_countアイテムのサイズによって65535に制限されます。ClassFile構造体のfields_count項目の値には、スーパークラスまたはスーパーインターフェースから継承されたフィールドが含まれていないことに注意してください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.