1

Java プログラムで非常に奇妙な動作が見られます。失敗は再現できないため、元のログを参照するだけです。

クラスは次のようになります。

public class MyClass {
    public static final String MY_CONSTANT_STRING = "This should never change";

    public boolean checkEndsWithCS(String inString) {
        return inString.endsWith(MY_CONSTANT_STRING);
    }

    public String getString() {
        return "Some text '" + MY_CONSTANT_STRING + "' some more text";
    }
}

ログを見ると、getString が "Some text '' some more text" を返し、checkEndsWithCS("These are not the chars you're looking for.") が true を返すケースが見られます。

この場合、MY_CONSTANT_STRING は "" であるとしか言えません。

他のクラスは MyClass を拡張しないため、より高いレベルのクラスでオーバーライドされることはありません。

ログにメモリ不足状態の兆候は見られません。これが最も可能性の高い原因のようです。

これは static final であるため、参照は変更されません。文字列は不変であるため、文字列は変更されません。

質問:

  1. これらはいつ実行されますか? 日食にブレークポイントを設定しましたが、ヒットすることはありません。
  2. 静的最終参照の不変文字列を変更する方法はありますか?
  3. そもそも文字列が割り当てられないようにする方法はありますか?
  4. 文字列または参照を含むメモリが他のオブジェクトまたはプロセスによって「破壊」される可能性はありますか?
  5. 私がこれについて正しい方法で考えていない他の微妙な落とし穴はありますか?

ここでの集合的な経験がこれを解き放つことができない場合、私はそれを私のデータに欠陥があるという兆候と見なし、その角度からそれを調べます.

4

2 に答える 2

3

Javaリフレクションを使用してフィールドの値を変更しfinalたり、オブジェクトのプライベートフィールドをいじったりすることができStringます。

ネイティブコード(nativeメソッドなど)がメモリを上書きする可能性もあり、その場合、一部のStringオブジェクトの長さがゼロに変わる可能性があります。

コードベースの何かがこの種のことをしている場合、原因を特定するのは困難になります。そして、次のような可能性を完全に見落としてはなりません。

  • それを行っているサードパーティのライブラリ、
  • 信頼できないコードがそれを実行している(サンドボックスなしで信頼できないコードを実行している場合)、
  • 既知のセキュリティ上の欠陥を悪用する何か...'パッチを適用して最新の状態に保たれていないcos、
  • ログファイルを妨害する何か(または誰か)。

または、探しているソースコードと一致するコードを実行していない可能性があります。


1)これらはいつ実行されますか?Eclipseにブレークポイントを設定しましたが、ヒットすることはありません。MY_CONSTANT_STRINGの割り当てにブレークポイントを設定しました...

そのコードは、クラスの静的初期化の一部として実行されます。ブレークポイントを設定する前に実行された可能性があります。または、デバッガーにバグがある可能性があります。

2)静的な最終参照内の不変の文字列を変更するための可能な方法はありますか?

はい。上記を参照。

3)そもそも文字列が割り当てられないようにする方法はありますか?

ここに記述されているコードだけを考えると、いいえ。ただし、静的初期化グラフにサイクルがある場合は、MY_CONSTANT_STRING割り当てられる前の値を確認できます。ただし、その値はnull...空の文字列ではありません。

4)文字列または参照を含むメモリが他のオブジェクトまたはプロセスによって「破壊」される可能性がある方法はありますか?

はい。上記を参照。

5)私がこれを正しい方法で考えていない他の微妙な落とし穴はありますか?

おそらく。この距離からあなたの心を読むことはできません:-)

于 2013-02-05T09:11:35.327 に答える
2

ほぼ間違いなく、次のいずれかです。

  1. これは実行している実際のコードではありません。実際のコードは、違いを説明する意味のある異なることを行います。この定数が使用されている宣言に移動するよう IDE に依頼してください。それはあなたが思うものではないかもしれません。
  2. これはソース コードですが、コンパイルされたコードは最新ではありません。実行していない/実行していないコードを実行/実行していないようです
  3. あなたは実際にこのクラスを呼び出していません

staticクラスが初期化されるとき、クラスのメソッドが呼び出される前、またはインスタンスが作成される前に、割り当てと初期化子が発生します。これは保証されています。String不変であり、final参照は代入後に変更されません。フィールドをオーバーライドすることはできず、静的なものをオーバーライドすることもできません。(確かに非表示にすることはできますが。)

このフィールドで観察できる唯一の他の値は ですnull。これは、そうである場合に発生しますが、割り当てられる前にブロックfinalで参照します。staticこれは困難であり、ある種の循環初期化シナリオでのみ発生する可能性があります。

JVM のバグを除いて (これは完全に不可能というわけではありません)、Java コードのアクションによって参照が破損することはありません。

于 2013-02-05T09:10:54.603 に答える