1

java.nio.ByteBuffer を介して UTF8 文字列を読み込もうとしています。サイズは unsinged int であり、もちろん Java にはありません。値を取得できるように、値を long に読み込みました。

私が抱えている次の問題は、long を使用してバイト配列を作成できないことです。long を int にキャストすると、署名されます。

また、バッファで limit() を使用してみましたが、これも int not long で動作します。

私が行っている特定のことは、クラスファイルから UTF8 文字列を読み取ることです。そのため、バッファーには UTF8 文字列だけではありません。

ByteBuffer から unsigned int の潜在的な長さを持つ UTF8 文字列を読み取る方法に関するアイデア。

編集:

問題の例を次に示します。

SourceDebugExtension_attribute {
       u2 attribute_name_index;
       u4 attribute_length;
       u1 debug_extension[attribute_length];
    }

attribute_name_index
    The value of the attribute_name_index item must be a valid index into the constant_pool table. The constant_pool entry at that index must be a CONSTANT_Utf8_info structure representing the string "SourceDebugExtension".

attribute_length
    The value of the attribute_length item indicates the length of the attribute, excluding the initial six bytes. The value of the attribute_length item is thus the number of bytes in the debug_extension[] item.

debug_extension[]
    The debug_extension array holds a string, which must be in UTF-8 format. There is no terminating zero byte.

    The string in the debug_extension item will be interpreted as extended debugging information. The content of this string has no semantic effect on the Java Virtual Machine.

そのため、技術的な観点から言えば、クラス ファイル内に完全な u4 (符号なし、4 バイト) の長さの文字列を含めることができます。

UTF8 文字列のサイズに制限がある場合、これらは問題になりません (私は UTF8 の専門家ではないので、おそらくそのような制限があるでしょう)。

私はただそれをパントして、それほど長いストリングが存在しないという現実を受け入れることができました...

4

4 に答える 4

6

バイト配列が 2GB ( Java の最大の正の値) を超えない限り、符号付き にバックintをキャストしても問題はありません。longint

バイト配列の長さが 2GB を超える必要がある場合は、間違っています。特に、JVM のデフォルトの最大ヒープサイズをはるかに超えているためです...

于 2009-03-08T20:09:53.680 に答える
1

Java 配列は、言語仕様に従ってアクセスに (Java、つまり符号付き) int を使用するため、Integer.MAX_INT よりも長い文字列 (char 配列に基づく) を持つことは不可能です。

しかし、それだけでも 1 つのチャンクで処理するには多すぎます。十分に大きな String が発生した場合、ほとんどのマシンでパフォーマンスが完全に失われ、OutOfMemoryError でプログラムが失敗します。

あなたがすべきことは、一度に数メガなど、適切なサイズのチャンクで文字列を処理することです。そうすれば、処理できるサイズに実質的な制限はありません。

于 2009-03-08T23:30:41.170 に答える
1

サインインすることはあなたの主な問題ではありません。長さが 40 億の String があるとします。少なくとも 4 GB の ByteBuffer、少なくとも 4 GB の byte[] が必要です。これを文字列に変換する場合、少なくとも 8 GB (1 文字あたり 2 バイト) とそれを構築するための StringBuilder が必要です。(少なくとも 8 GB) 必要なすべて、1 つの文字列を処理するのに 24 GB。多くのメモリを持っていても、このサイズの多くの文字列を取得することはできません。

もう 1 つの方法は、長さを符号付きとして扱い、符号なしの場合はいずれにしても文字列を処理するのに十分なメモリがないため、エラーとして扱うことです。長さが 20 億 (2^31-1) の文字列を処理する場合でも、この方法で文字列に変換するには 12 GB が必要です。

于 2009-03-08T20:15:59.563 に答える
0

ByteBufferの上にCharSequenceを実装できると思います。これにより、「文字列」がヒープに表示されないようにすることができますが、文字を処理するほとんどのユーティリティは実際には文字列を想定しています。それでも、実際にはCharSequenceにも制限があります。サイズがintとして返されることを期待しています。

(理論的には、サイズをlongとして返す新しいバージョンのCharSequenceを作成できますが、Javaには、そのCharSequenceの処理に役立つものはありません。subSequence(...)を実装すると便利です。通常のCharSequenceを返します。)

于 2009-10-10T09:44:21.170 に答える