[解決済み] Java 8 のコンストラクタ参照で恐ろしいパフォーマンスと大きなヒープフットプリント?
質問
本番環境において、かなり不愉快な経験をしました。
OutOfMemoryErrors: heapspace..
この問題の原因をたどると、私が使っている
ArrayList::new
を関数で使用したことに起因します。
これが実際に宣言されたコンストラクタを介した通常の作成よりも悪いパフォーマンスであることを検証するために、(
t -> new ArrayList<>()
) を介しての通常の作成よりも実際にパフォーマンスが悪いことを確認するために、次のような小さなメソッドを書きました。
public class TestMain {
public static void main(String[] args) {
boolean newMethod = false;
Map<Integer,List<Integer>> map = new HashMap<>();
int index = 0;
while(true){
if (newMethod) {
map.computeIfAbsent(index, ArrayList::new).add(index);
} else {
map.computeIfAbsent(index, i->new ArrayList<>()).add(index);
}
if (index++ % 100 == 0) {
System.out.println("Reached index "+index);
}
}
}
}
このメソッドを
newMethod=true;
で実行すると、このメソッドは
OutOfMemoryError
で失敗します。この場合
newMethod=false;
では、プログラムは失敗せず、殺されるまで叩き続けます (インデックスは簡単に 150 万に達します)。
なぜ
ArrayList::new
がこんなにたくさん
Object[]
要素がヒープ上に生成され、それが
OutOfMemoryError
を発生させるほど速いのですか?
(ちなみに - コレクションの型が
HashSet
.)
どのように解決するのですか?
最初のケース (
ArrayList::new
) では
のコンストラクタを使用しています。
を使用している場合、2番目のケースはそうではありません。大きな初期容量 (
index
を指定した場合) は、大きな
Object[]
が確保され、その結果
OutOfMemoryError
s.
以下は2つのコンストラクタの現在の実装です。
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
似たようなことが
HashSet
ただし,配列が確保されるのは
add
が呼び出されるまで配列は割り当てられません。
関連
-
Springの設定でxsdファイルのバージョン番号を設定しない方が良い理由
-
プロジェクトの依存関係を解決できない。
-
SpringBoot 起動エラー java.nio.charset.MalformedInputException: 入力長 = 2 解決
-
アノテーション「@Retention」の役割
-
Javaがリソースリークに遭遇した:'input'が閉じない 解決方法
-
春ブート複数のデータソースの管理(atomikos)同じサーバーホスト上の複数のプロジェクトを開始する複数のJava - jarのエラーソリューション
-
[解決済み] Java で、あるコンストラクタを別のコンストラクタから呼び出すにはどうすればよいですか?
-
[解決済み] Javaにおける例外処理によるパフォーマンスへの影響とは?
-
[解決済み] java.lang.OutOfMemoryError" の対処法。Java heap space "エラーの対処方法を教えてください。
-
[解決済み] Java コンストラクタ継承
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
javaの非静的メソッドを静的に参照することができない
-
プロジェクトの依存関係を解決できない。
-
無効なメソッド宣言
-
BindException: アドレスはすでに使用中です:バインドエラー解決
-
SocketException java.netの4つの例外解決策。
-
配列定数は初期化子でのみ使用可能です。
-
CertificateException: XXXに一致するサブジェクトの代替DNS名が見つかりません 解決策
-
java send https request prompt java.security.cert.について。
-
Junitのユニットテストエラー
-
eclipse にリソースリーク:'in' が閉じない