web-dev-qa-db-ja.com

Javaに関して「スペースリーク」という用語を使用することは意味がありますか?

Javaで「メモリリーク」が発生する可能性があるかどうかについて、メインスタックオーバーフローコミュニティのいくつかの投稿を偶然見つけました。つまり、Javaアプリケーションにはメモリリークがありません(または、見方によっては常にメモリリークがあります)が、「スペースリーク」があります。

この用語をどこから取得したのか思い出せないので、簡単に検索して、思いもよらなかったことや、Haskellや遅延評価に関して使用されているようです。 ここ 、私は信頼できると思われる簡潔な定義を見つけました。

コンピュータプログラムが必要以上のメモリを使用すると、スペースリークが発生します。リークしたメモリが決して解放されないメモリリークとは対照的に、スペースリークによって消費されたメモリは解放されますが、予想より遅れます。

前世紀に私が教えた「メモリリーク」の概念は、メモリの割り当てを解除せずにトラックを失うことによって引き起こされました。これは、プログラムを理解しなくても検出できるものであり、GCがガベージとは何かを知るために使用する正確な条件です。 Javaで「メモリリーク」と呼ばれているものは、「スペースリーク」という用語とより密接に一致しているように見えます。する必要があります。

この区別は、管理されたメモリ言語についての議論を明確にするのに役立つと思いますが、それが長すぎるかどうかはわかりません。遅すぎるかもしれませんが、「メモリリーク」という用語を特定しておき、過負荷ではなく、同様の結果を生成するが原因が異なるものに適用するのが最善だと思います。

明確にするために、マネージアプリケーションでリークが発生しないことをお勧めしません。私はそれらについてどのように話すかについて単に考えています。メモリリークおよびJavaには、 'fanboy' slursによる炎上戦争が含まれ、この正確な質問を中心とするような非常に賛成の議論があります。実際、私の質問でさえ誤解されていると、用語の問題です。

5
JimmyJames

Javaに関して「スペースリーク」という用語を使用することは意味がありますか?

率直に言って、いいえ。

この用語は十分に根拠があり、Haskellコミュニティでは理解されています(または理解される可能性があります)が、「スペースリーク」と「メモリリーク」の違いは、Java=開発者には理解されていませんまたは幅広いソフトウェアエンジニアリングコミュニティ1

したがって、「スペースリーク」と「メモリリーク」を区別すると、照明ではなく混乱が生じる可能性があります。

この用語が「明確にする」かどうかの問題について... IMO、必ずしもではない:

  1. この「新しい」用語を使わなくても、同様に明確にすることができます。たぶんもっともっと...あなたが話していることを完全に着手すれば...

  2. 人々が理解していない用語を使用しても、明確にはなりません。


1-たとえば、40年以上プログラミングしていて、Javaで15年以上もの間、このように「スペースリーク」が使用されたことを思い出すことはできません。 。 今まで。

16
Stephen C

番号。

最近のほとんどすべてのプログラムは、必要以上の領域を使用しています。あなたのJavaプログラムがオブジェクトを生き続けるようにプログラマーがコレクションに適格であると考えている場合)、それはメモリリークです。これはよく知られた一般的な用語です。はい、少し異なりますコンテキストによって、しかし、基礎となる概念は精神的ジャンプが非常に短いほど十分に近いです。

ペダントリーはここでは何の利益も提供しません。

30
Telastyn

おそらく、ここでの違いは、物理的リークと論理的リークとして説明できます。 GCは前者に対して優れた保護を提供します。

しかし、一般的に「メモリリーク」についてだけ言えば、GCは非常に強力な保護を提供しておらず、それを回避することをさらに困難にする可能性があることをお勧めします。これは物議を醸しているので、慎重に説明しようと思います(また、GCが欠落している場合に存在する安全上の欠点のうち、確実に存在するものについても)。

私にとって、GCが提供する最大の利点は、リークからの保護ではなく、リークが最大の問題ではない場合に安全を提供することです。

ビデオゲームの例を見てみましょう。おそらく人々は、熱狂的なゲーム開発者によって書かれたいくつかのゲームを、狂ったようにリソースをリークするガベージコレクションを提供する言語で試したことがあるでしょう。ゲームをプレイしてから30分以内に、単純な2Dゲームのメモリ使用量はギガバイトに増加し、ゲームが再起動するまで長時間使用すると、ゲームの速度はますます遅くなります。 1年間の開発と16回の更新後、ゲームは相変わらず未だに漏洩しています。

これらのタイプのリークゲームは、ほとんどの場合、ガベージコレクターに対して作成される傾向がありますが、最もリークの多いアプリケーションの1つです。一部の人がメモリリークに対する特効薬であるとGCが見なしているとしたらどうでしょうか。

これらのゲームは、あまり経験のない開発者によって開発されることが多いため、比較は公平ではない場合があります。しかし、私はこれらのゲーム開発者がガベージコレクションを使用しなかった場合、リークの少ない(ただしクラッシュの多い)ソフトウェアを作成することをお勧めします。

リソースの管理不良

これらのリークが発生する理由は、ルート化されたリソースが原因です。より一般的に言えば、これらはリソースの管理不良の結果であり、GCの有無にかかわらず発生する可能性がある問題です。ゲームはゲームプレイ中にスプライトを繰り返し割り当てる場合がありますが、コードベースの複数の領域がこれらのスプライトを参照する場合があります。これらの場所のいずれかで参照を手動で解放しないと、ルート化されたリソースが必要なくなったときに解放されず、アプリケーションがシャットダウンされるまでまったく解放されないという、恐ろしい論理リークが発生します。

安全

それでも、ゲームはクラッシュすることなく実行され続けます。不要になったスプライトや描画されていないスプライトを不必要にループし、次第に遅くなり、不要なスプライトの蓄積によりますます多くのメモリを消費します。それにもかかわらず、これらのアマチュア風のインディゲームでさえ、どれほど安定(クラッシュなし)であるかは注目に値します。そのため、GCが大きなメリットを提供していると私は思います。

ダングリングポインターと未解放のリソース

GCを使用しないネイティブコードベースが指定された同様のシナリオでは、リソースは、その参照(ポインター)のいずれか1つを介してリソースを解放する明示的な要求によって解放されます。これにより、他の参照(ポインター)が無効になります(ダングリングポインターになります)。その後、ゲームの一部でぶら下がりポインタにアクセスすると、非常に致命的な未定義の動作が発生します。通常、segfault /アクセス違反が原因でハードクラッシュが発生します。

ここでのセグメンテーションフォールトは、非常に目を見張るようなバグであり、クラッシュを引き起こします。それにもかかわらず、それは明らかに明白であり、検出して修正するのは簡単です。そのため、最終的にメモリリークを回避するためのEdgeは、実際にはガベージコレクションを使用しない言語に使用されると思います(後でいくつかのパッチがあります)。修正するのが最も簡単なバグは、気づく/再現するのが最も簡単です。代わりに、GCを使用しないこれらの言語は、より危険なコードと、より低いメモリ管理レベルでのリソースの誤った管理に起因する未定義の動作によって、その代償を払っています。 GC言語は、テストのレーダーの下で飛行する可能性のある安全でありながら、欺瞞的で微妙な漏洩動作という形で、リソースの誤管理の代償を払うことができます。

これは、サードパーティのプラグインをロードすると、そのプラグインがシステム内のリソースへの参照を取得する拡張可能なプラグインアーキテクチャで特に煩わしい場合があります。たとえば、300メガバイトに及ぶ巨大な画像があります。そのプラグインコード(自分の制御下にない)が手動で参照を解放できない場合、そのプラグインが存在するだけで、コードベースは不思議なことに300メガバイトのリソースをあちこちにリークします。このサードパーティのプラグインの。

銀の弾丸

とにかく、私はさまざまな種類のリークをそれほど区別しないようにすることをお勧めします。それらはすべて同じように迷惑です(実際には、論理的なリークが最も煩わしい傾向があります)。代わりに、ガベージコレクションはメモリリークに対する特効薬ではないという事実に焦点を当てようと思います。この種の幻想を購入することは、非常に漏洩しやすいソフトウェアを招くことがよくあります。メモリリークを回避する強い動機がある場合、GCを前もって持つ言語のソフト/弱/ファントム参照などの概念に特別な注意を払うことは価値があります。リソース管理は必ずしもGCで簡単になるとは限らず、場合によってはさらに難しくなることもあります。それは、誤った管理によって致命的な動作が少なくなる傾向があるということです(実際には、状況によっては良いことも悪いこともある)。

valgrindなどのリーク検出ツールを使用すると、アプリケーションのシャットダウン後も解放されなかったメモリを割り当てたコード行がすぐに表示されるため、GCが完全に回避する物理リークは最も簡単に回避できることにも注意してください。通常、論理的なリークははるかに困難であり、GCや他のツールでは効果的に私たちを保護することはできません。複雑なリソース管理が関与する場合は、慎重な設計と実装のみが必要です。

7
user204677

主な違いは時間の面です。リンクされた記事に記載されているスペースリークが発生beforeユーザーは結果を終了しますが、メモリリークが発生しますafter。ユーザーがスペースリーク状態の結果で終了するとすぐに、ガベージコレクションが実行され、必要以上のメモリが一時的に使用されます。

メモリリークによってメモリが解放されることはありません。ユーザーが所定の結果で終了した後でも、プログラムがクラッシュするまで、メモリリークは増加し続けます。この種の問題は、実際にガベージコレクションされた言語で発生する可能性があります。技術的には、まだどこかでメモリを参照していますが、意図的にユーザーに見える方法で参照しているわけではありません。

5
Karl Bielefeldt

多分。 GCが存在する場合の「メモリリーク」は、次の2つのいずれかを意味します。

  1. メモリがガベージコレクターの通知を実際にOSレベルで解放されずにエスケープする、ガベージコレクターまたは言語ランタイムの欠陥。それが存在することをだれも知らないので、解放されません(少なくともプロセスが終了するまでは)。

  2. オブジェクトが不要になった後、たとえば循環参照や字句閉包などによってオブジェクトが参照され続ける(おそらく無期限に)場合のユーザーコードの欠陥。 GCは、オブジェクトがまだ参照されていることを認識しているため、オブジェクトを解放しません。あなたが参照している記事はこれを「スペースリーク」と呼んでいますが、最も合理的な人々はそれをメモリリークの簡単な例と考えていると思います。

ただし、これらのいずれも発生せず、損失がそれほど永続的ではない場合が他にもいくつかあります。

  1. オブジェクトはGCによって適切に管理されており、適切に参照されていませんが、実際にはまだ収集されていません。おそらく、GCをトリガーする条件がまだ発生していないか、何らかの条件によってGCが一時的に妨げられているためです。メモリは将来的に理論的に利用可能になりますが、現在ではなく、プログラムの低レベルのメモリ使用量は、実際のワーキングセットを大幅に超えます。

  2. プログラムは大量のメモリを割り当て、それで終了し、GCはそれを適切に解放しましたが、それを行うための条件がまだ満たされていないため、まだOSに返されていません。特定のOSでは不可能、またはランタイムがmakeに書き込まれていないため、可能です。メモリは同じプログラムによる将来の割り当てに使用できますが、他のプログラムには使用できません。外部からプログラムのメモリ使用量は増加しますが、減少しません。

これらのケースは、最終的に解決する傾向があるため、通常、適切なメモリリークよりもはるかに問題が少なくなります。タイトなループや大きな一時的な割り当てなど、特定の言語/ランタイム/ OSの魔法の組み合わせです。次に、対処しなければならない問題があります。

要するに、メモリリークはGCによって追放されず、依然として懸念事項です。作成するのはharderだけです。しかし、いつかは遭遇する可能性のある他の種類の問題も存在します(うまくいけばそうはいきませんが)。 「スペースリーク」は実際には妥当な名前だと思いますが、これはリンクした記事と矛盾しているため、おそらく別の何かです。

4
hobbs

Cでは、オブジェクトにメモリを割り当て、そのオブジェクトへのすべての参照を破棄すると、プログラムはそのメモリを確実に回復できません。これを繰り返し実行するプログラムは、多くのメモリを消費することになります。通常、時間の経過とともにますます多くのメモリを消費します。

Javaでは発生しません。ガベージコレクションにより、到達できないすべてのオブジェクトのメモリが回復されるためです。Javaで頻繁に発生するのは、オブジェクトがプログラムがもう必要としないものもあり、これらはプログラムがOutOfMemoryErrorを取得するまで時間とともに蓄積されます。

これらのシナリオはどちらも、何千人ものプログラマーによって「スペースリーク」と一般的に呼ばれていますが、これは事実についての論争ではないであることに注意することが重要です。ここに事実の違いを理解しているにもかかわらず、両方に同じ用語を使用している無数の知識豊富な人々がいます。

だからあなたの質問は完全に用語であり、私が与えることができる最高のアドバイスは、「スペースリーク」という用語を見るときはいつでも、コンテキストに基づいて、著者が話しているこれら2つの状況のどちらを判断する必要があるということです。

1
sacundim