Java7および8のメソッドの最大サイズ


82

Javaではメソッドが64KBを超えることはできないことを知っています。この制限により、JavaCC文法から生成されたコードで問題が発生します。Java 6に問題があり、文法を変更することでこれを修正することができました。Java 7の制限は変更されましたか、それともJava 8で計画されていますか?

明確にするためだけに。自分で64KBを超えるメソッドは必要ありません。しかし、私は非常に大きなメソッドにコンパイルされる文法を書きました。


4
巨大なbrainf ** kコードをコンパイルしようとしたときに、同じ問題に直面しました。
johnchen902 2013

3
反対の情報がないので、この制限はJava 8でも引き続き適用されると考えるのが安全だと思います...もちろん、別の(コストのかかる)オプションは、パーボイルドの文法エンジンを変更することです。純粋なJavaで文法を書いてください。
fge 2013

4
見ていこの記事
Anirudha

7
個人的には、このような大きなメソッドを作成することはJavaCCのバグだと思います。それは本当にそのコードを広めることができるはずです。特に、JVMがそのような巨大なメソッドを最適化するために構築されていないことを考えると。
ヨアヒムザウアー2013

回答:


58

JVMS7によると:

end_pcが排他的であるという事実は、Java仮想マシンの設計における歴史的な誤りです。メソッドのJava仮想マシンコードが正確に65535バイトの長さで、1バイトの長さの命令で終わる場合、その命令は保護できません。例外ハンドラーによる。コンパイラライターは、任意のメソッド、インスタンス初期化メソッド、または静的初期化子(任意のコード配列のサイズ)に対して生成されるJava仮想マシンコードの最大サイズを65534バイトに制限することにより、このバグを回避できます。

しかし、これは約Java 7です。Java 8の最終的な仕様はないため、(開発者を除いて)誰もこの質問に答えることができませんでした。

UPD(2015-04-06)JVM8によると、これはにも当てはまりますJava 8


2
本当にJavaにはまだ修正されていないような「バグ」がありますか?特にLaurentGの状況では、大きな制限になる可能性があります。
フランチェスコベラドンナ2013

3
@ Fire-Dragon-DoL引用された議論は、メソッドの長さがそうでない場合よりも1バイト短くなければならないことについてのみです。これはまったく重要ではありません。この制限は、そのような単純な「バグ」によるものではありません。バイトコード全体的な設計にあり、修正するには、全体を再指定する必要があります。
Marko Topolnik 2014

11

良い質問。いつものように、ソースにアクセスし答えを見つける必要があります(「Java®仮想マシン仕様」)。このセクションでは、(Java6 VM仕様のように)制限については明示的に言及していませんが、多少慎重に説明しています。

メソッドの呼び出し時に作成されるフレームのローカル変数配列内のローカル変数の最大数(§2.6)は、コード属性(§4.7.3)のmax_locals項目のサイズによって65535に制限されます。メソッド、およびJava仮想マシン命令セットの16ビットローカル変数インデックスによる。

乾杯、


5
「ローカル変数の最大数」はたまたま同じ数値ですが、それでも「メソッドの最大サイズ」とはまったく異なるものであるとOPは求めました。
ホルガー2017

8

変わっていません。メソッド内のコードの制限は、Java7とJava8の両方で64KBのままです。

参照:

  1. Java 7仮想マシン仕様(4.9.1静的制約)から:

クラスファイル内のJava仮想マシンコードの静的制約は、Java仮想マシン命令をコード配列に配置する方法と、個々の命令のオペランドを指定する必要があります。

コード配列内の命令に対する静的制約は次のとおりです。

  • コード配列は空であってはならないため、code_lengthアイテムの値を0にすることはできません。
  • code_lengthアイテムの値は65536未満である必要があります。
  1. Java 8仮想マシン仕様(4.7.3コード属性)から:

code_length項目の値は、このメソッドのコード配列のバイト数を示します。

code_lengthの値は、ゼロより大きく(コード配列が空であってはならないため)、65536未満である必要があります。


1

Andremoniyはjava 7すでにこの質問の一部に回答していますが、その時点ですぐに決定されたjava 8ようですので、その部分をカバーするために回答を完成させます。

以下からの引用のJVM

end_pcが排他的であるという事実は、Java仮想マシンの設計における歴史的な誤りです。メソッドのJava仮想マシンコードが正確に65535バイトの長さで、1バイトの長さの命令で終わる場合、その命令は保護できません。例外ハンドラーによる。コンパイラー作成者は、任意のメソッド、インスタンス初期化メソッド、または静的初期化子(任意のコード配列のサイズ)に対して生成されるJava仮想マシンコードの最大サイズを65534バイトに制限することにより、このバグを回避できます。

ご覧のとおり、この歴史的な問題は、少なくともこのバージョン(java 8)では解決されていないようです。


-1

回避策として、パーサーのコードにアクセスできる場合は、JVMコンパイラーによって課せられる制限内で機能するように変更できます...(パーサーコード内の部分を見つけるのに永遠にかかることはないと仮定します。変更)

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