StringBuffer、および古いコードのレガシーを取り除くことの難しさ

みなさんこんにちは。 この記事は、 StringBufferによる投稿の無料翻訳であり、 レガシーコードを取り除くのがどれほど難しいかを示しています 。 どういうわけか彼は本当に私の魂に沈んだので、彼は翻訳することにしました。 行こう

2006年、 StringBuilderは5番目のjavaに登場しました。 StringBufferでスマートな代替品。 公式の StringBuffer ドキュメントに StringBuffer次のStringBuffer

このクラスは、単一のスレッドで使用するための同様のクラスであるStringBuilderによって補完されます。 一般に、StringBuilderクラスを優先する必要があります。これは、このクラス(StringBuffer)と同じすべての操作をサポートしますが、同期を実行しないため高速です。

StringBuffer synchronizedすることは決して良い考えではありませんでした。 主な問題は、1つの操作だけでは十分ではないことです。 .append(x)単一の連結は、 .append(y).toString()などの他の操作がなければ.append(y) 。 特定の各メソッドがスレッドセーフであるとき、スレッド間の競合なしに複数の呼び出しを行うことはできません。 唯一のオプションは外部同期です。

それで何? 10年後、誰もStringBufferを使用していないことが判明しました!? まあ、少なくとも、間違いなく新しい機能のためではありません!?

このコードはいくつのオブジェクトを作成しますか?


前に書いたように、仮想マシンは起動時またはメインライブラリのロード時に多くのオブジェクトを作成します。 上記の質問をすることで想像できる以上のことができます:

 public class Main { public static void main(String... args) { System.out.println("Hello " + "world"); } } 

バージョン8のOracle JVMは、このプログラムを実行するために約10_000個のオブジェクトを作成します。

StringBuffersはどのくらい作成しますか?


したがって、JVMを実行するには、多くのオブジェクトを作成する必要がありますが、10年は使用すべきではない、より高速な代替手段を持つ古いクラスを作成する必要がありますか?

 public class Main { public static void main(String[] args) throws IOException { System.out.println("Waiting"); System.in.read(); } } 

プロセスの実行中に、次のコマンドを実行できます。

 jmap -histo {pid} | grep StringBuffer 

取得:

  18: 129 3096 java.lang.StringBuffer 

129は、Java 8 Update 121が作成したStringBufferオブジェクトの数です。これは、前回チェックしたときよりも少ないですが、それでも少し驚くほどです。

(Java 8アップデート131で131をチェックし、14個のオブジェクトのみを受け取りました)。

新機能-ラムダとストリームはどうですか? これらは過去10年間に明示的に作成され、Objectwebs ASMなどのサードパーティライブラリを使用しています。 そして、これらの開発者は仮想マシンの内部を正確に知っており、新しい機能をできるだけ軽量に設計する必要がありました。

 public class Main { public static void main(String[] args) throws IOException { IntStream.range(0, 4).forEach(System.out::println); System.out.println("Waiting"); System.in.read(); } } 

jmap再び起動すると、何が表示されますか?

  17: 545 13080 java.lang.StringBuffer 

最も単純なラムダとストリーム用の追加の416オブジェクト!

(再びJava 8アップデート131で131をチェックし、430オブジェクト、つまり同じ416オブジェクトの違いを受け取りました。ストリームとラムダはクリーンアップしなかったようです)。

ところで、上記のプログラムは一般に次のものを作成します。

 Total 35486 4027224 

または35_486オブジェクト!

結論


もちろん、アプリケーションの開始時にStringBufferを使用しても大きな違いはありませんが、適切な代替手段があり、StringBufferは新しい機能でも使用されていることを知っています。古いコードのレガシーを取り除くことや、ベストプラクティスを使用するために人々の心を変えることがいかに難しいかを示しています。

PS
元の投稿では、彼らは9-keでStringBufferからのクリーンアップチケットへのリンクを残しました。
したがって、3か月後にはレガシーなしで放置される可能性が非常に高くなります。ただし、それはStringBufferについてのみです。 VectorHashtable 、およびその他のアメニティを忘れないでください。

Source: https://habr.com/ru/post/J329956/


All Articles