検索
ホームページJava&#&チュートリアルJavaでメモリリークを引き起こすコードを記述する方法

このテキストは、StackOverflow Q&A Web サイトで人気のあるディスカッション「メモリ リークを引き起こす Java でコードを記述する方法」から引用したものです。

Q: 面接に参加したところ、面接官がメモリリークを引き起こす Java コードの書き方を尋ねました。この質問については全く分かりません、とても恥ずかしいです。

A1: メモリ リークは、次の手順で簡単に発生する可能性があります (プログラム コードは特定のオブジェクトにアクセスできませんが、オブジェクトはメモリに保存されています):

アプリケーションは、長時間実行されるスレッドを作成します (または、スレッド プールを使用します。漏れが早く発生します)。

スレッドは、特定のクラスローダー (カスタマイズ可能) を通じてクラスをロードします。

このクラスは、大きなメモリ ブロック (new byte[1000000] など) を割り当て、静的変数に強参照を格納してから、独自の参照を ThreadLocal に格納します。追加のメモリ new byte[1000000] の割り当てはオプションです (クラス インスタンス リークで十分です)。ただし、これによりメモリ リークが速くなります。

スレッドは、カスタム クラスまたはクラスをロードするクラス ローダーをクリーンアップします。

上記の手順を繰り返します。

クラスおよびクラスローダーへの参照がないため、ThreadLocalのストレージにアクセスできません。 ThreadLocal はオブジェクトへの参照を保持し、クラスとそのクラス ローダーへの参照も保持します。そのため、クラス ローダーはロードするクラスへのすべての参照を保持するため、GC は ThreadLocal に格納されているメモリを再利用できません。多くの JVM 実装では、Java クラスとクラス ローダーは GC を実行せずに permgen 領域に直接割り当てられるため、より深刻なメモリ リークが発生します。

このリーク パターンの変形の 1 つは、ThreadLocal を任意の形式で使用するアプリケーションやアプリケーション コンテナー (Tomcat など) を頻繁に再デプロイすると、メモリ リークが容易に発生することです (アプリケーション コンテナーは前述のようにスレッドを使用するため、新しいクラスローダーがアプリが再デプロイされるたびに使用されます)。

A2:

静的変数参照オブジェクト

class MemorableClass {
    static final ArrayList list = new ArrayList(100);
}

長い文字列のString.intern()を呼び出す

String str=readString(); // read lengthy string any source db,textbox/jsp etc..
// This will place the string in memory pool from which you cant remove
str.intern();

開いたストリーム(ファイル、ネットワークなど)は閉じられていない

try {
    BufferedReader br = new BufferedReader(new FileReader(inputFile));
    ...
    ...
} catch (Exception e) {
    e.printStacktrace();
}

接続は閉じられていない

try {
    Connection conn = ConnectionFactory.getConnection();
    ...
    ...
} catch (Exception e) {
    e.printStacktrace();
}

JVMのGCが利用できない領域に到達

例えば、ネイティブメソッドで割り当てられたメモリ。

アプリケーションスコープ内のWebアプリケーションのオブジェクト、アプリケーションは再起動されていないか、明示的に削除されていません

getServletContext().setAttribute("SOME_MAP", map);

セッションスコープ内のWebアプリケーションのオブジェクトは、無効化されていない、または明示的に削除されていない 削除

session.setAttribute("SOME_MAP", map);

不正または不適切なJVMオプション

例えば、IBM JDKのnoclassgcは、無駄なクラスのガベージコレクションを防ぎます

A3: HashSetの場合hashCode() または equals() が正しく実装されていない (または実装されていない) と、「コピー」がコレクションに追加され続けます。コレクションが無視すべき要素を無視できない場合、コレクションのサイズは増大し続けるだけであり、これらの要素は削除できません。

間違ったキーと値のペアを生成したい場合は、次のようにすることができます:

class BadKey {
   // no hashCode or equals();
   public final String key;
   public BadKey(String key) { this.key = key; }
}
  
Map map = System.getProperties();
map.put(new BadKey("key"), "value"); // Memory leak even if your threads die.

A4: 忘れられたリスナー、静的参照、ハッシュマップ内のキーエラー/変更に加えて、ライフサイクルを終了できないスレッドブロック、メモリ リークのシナリオ。ここでは、主にスレッドに関連する、それほど明白ではない Java メモリ リークのシナリオをいくつか紹介します。

Runtime.addShutdownHook は削除されません。removeShutdownHook を使用しても、未起動スレッドに対する ThreadGroup クラスのバグにより、リサイクルされず、ThreadGroup でメモリ リークが発生する可能性があります。

スレッドは作成されるが開始されない、上記と同じ状況

ContextClassLoader と AccessControlContext を継承するスレッドの作成、ThreadGroup と InheritedThreadLocal の使用、これらすべての参照は潜在的なリークであり、クラス ローダーによってロードされたすべてのクラスと同様に、静的参照など。これは、j.u.c.Executor フレームワーク (java.util.concurrent) 全体の重要なコンポーネントである ThreadFactory インターフェイスに非常に明白な影響を与えますが、多くの開発者はその潜在的な危険性に気づいていません。そして多くのライブラリはリクエストに応じてスレッドを開始します。

ThreadLocal キャッシュは多くの場合、良い習慣ではありません。 ThreadLocal に基づいた単純なキャッシュの実装は数多くありますが、スレッドが予想されるライフサイクルを超えて実行され続けると、ContextClassLoader がリークします。本当に必要な場合を除き、ThreadLocal キャッシュを使用しないでください。

ThreadGroup.destroy() は、ThreadGroup 自体にスレッドがなくても、子スレッド グループがまだある場合に呼び出されます。メモリ リークが発生すると、スレッド グループを親スレッド グループから削除できず、子スレッド グループを列挙できなくなります。

WeakHashMapを使用すると、値が直接(間接的に)キーを参照するため、見つけるのが困難になります。これは、Weak/SoftReference を継承するクラスが保護されたオブジェクトへの強い参照を保持する可能性がある場合にも当てはまります。

リソースをダウンロードするには、http(s)プロトコルのjava.net.URLを使用します。 KeepAliveCache はシステム ThreadGroup に新しいスレッドを作成し、現在のスレッドのコンテキスト クラス ローダー メモリのリークを引き起こします。スレッドは、生き残っているスレッドがない最初のリクエストで作成されるため、リークが発生する可能性が非常に高くなります。 (これは Java 7 で修正されており、スレッドを作成するコードはコンテキスト クラス ローダーを適切に削除します。)

InflaterInputStream を使用して、コンストラクター (PNGImageDecoder など) で新しい java.util.zip.Inflater() を渡します。インフレーターの end() は呼び出しません。 new だけは非常に安全ですが、コンストラクターのパラメーターとしてクラスを自分で作成し、ストリームの close() を呼び出してインフレーターを閉じることができない場合、メモリ リークが発生する可能性があります。これはファイナライザーによって解放されるため、実際にはメモリ リークではありません。しかし、これはネイティブ メモリを大量に消費するため、Linux の oom_killer がプロセスを強制終了させます。したがって、このことから得られる教訓は、ネイティブ リソースをできるだけ早くリリースするということです。

同じことが java.util.zip.Deflater にも当てはまりますが、これはさらに深刻です。デフレーターがほとんど使用されないのが良いことかもしれません。デフレーターまたはインフレーターを自分で作成する場合は、end() を呼び出す必要があることに注意してください。


声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
高度なJavaプロジェクト管理、自動化の構築、依存関係の解像度にMavenまたはGradleを使用するにはどうすればよいですか?高度なJavaプロジェクト管理、自動化の構築、依存関係の解像度にMavenまたはGradleを使用するにはどうすればよいですか?Mar 17, 2025 pm 05:46 PM

この記事では、Javaプロジェクト管理、自動化の構築、依存関係の解像度にMavenとGradleを使用して、アプローチと最適化戦略を比較して説明します。

適切なバージョン化と依存関係管理を備えたカスタムJavaライブラリ(JARファイル)を作成および使用するにはどうすればよいですか?適切なバージョン化と依存関係管理を備えたカスタムJavaライブラリ(JARファイル)を作成および使用するにはどうすればよいですか?Mar 17, 2025 pm 05:45 PM

この記事では、MavenやGradleなどのツールを使用して、適切なバージョン化と依存関係管理を使用して、カスタムJavaライブラリ(JARファイル)の作成と使用について説明します。

カフェインやグアバキャッシュなどのライブラリを使用して、Javaアプリケーションにマルチレベルキャッシュを実装するにはどうすればよいですか?カフェインやグアバキャッシュなどのライブラリを使用して、Javaアプリケーションにマルチレベルキャッシュを実装するにはどうすればよいですか?Mar 17, 2025 pm 05:44 PM

この記事では、カフェインとグアバキャッシュを使用してJavaでマルチレベルキャッシュを実装してアプリケーションのパフォーマンスを向上させています。セットアップ、統合、パフォーマンスの利点をカバーし、構成と立ち退きポリシー管理Best Pra

キャッシュや怠zyなロードなどの高度な機能を備えたオブジェクトリレーショナルマッピングにJPA(Java Persistence API)を使用するにはどうすればよいですか?キャッシュや怠zyなロードなどの高度な機能を備えたオブジェクトリレーショナルマッピングにJPA(Java Persistence API)を使用するにはどうすればよいですか?Mar 17, 2025 pm 05:43 PM

この記事では、キャッシュや怠zyなロードなどの高度な機能を備えたオブジェクトリレーショナルマッピングにJPAを使用することについて説明します。潜在的な落とし穴を強調しながら、パフォーマンスを最適化するためのセットアップ、エンティティマッピング、およびベストプラクティスをカバーしています。[159文字]

Javaのクラスロードメカニズムは、さまざまなクラスローダーやその委任モデルを含むどのように機能しますか?Javaのクラスロードメカニズムは、さまざまなクラスローダーやその委任モデルを含むどのように機能しますか?Mar 17, 2025 pm 05:35 PM

Javaのクラスロードには、ブートストラップ、拡張機能、およびアプリケーションクラスローダーを備えた階層システムを使用して、クラスの読み込み、リンク、および初期化が含まれます。親の委任モデルは、コアクラスが最初にロードされ、カスタムクラスのLOAに影響を与えることを保証します

See all articles

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

AtomエディタMac版ダウンロード

AtomエディタMac版ダウンロード

最も人気のあるオープンソースエディター

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

このプロジェクトは osdn.net/projects/mingw に移行中です。引き続きそこでフォローしていただけます。 MinGW: GNU Compiler Collection (GCC) のネイティブ Windows ポートであり、ネイティブ Windows アプリケーションを構築するための自由に配布可能なインポート ライブラリとヘッダー ファイルであり、C99 機能をサポートする MSVC ランタイムの拡張機能が含まれています。すべての MinGW ソフトウェアは 64 ビット Windows プラットフォームで実行できます。

EditPlus 中国語クラック版

EditPlus 中国語クラック版

サイズが小さく、構文の強調表示、コード プロンプト機能はサポートされていません

Dreamweaver Mac版

Dreamweaver Mac版

ビジュアル Web 開発ツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター