検索ハンドルオブジェクトを開いたままにしておくと、クエリキャッシュに役立つ検索ライブラリを使用しています。時間の経過とともに、キャッシュが肥大化する傾向があり(数百メガバイトで成長し続ける)、OOMが起動し始めました。このキャッシュの制限を強制したり、使用できるメモリの量を計画したりする方法はありません。そのため、 Xmxの制限を増やしましたが、これは問題の一時的な解決策にすぎません。
最終的に、私はこのオブジェクトをの指示対象にすることを考えていますjava.lang.ref.SoftReference
。したがって、システムの空きメモリが不足すると、オブジェクトが解放され、オンデマンドで新しいオブジェクトが作成されます。これにより、新たに開始した後の速度がいくらか低下しますが、これはOOMを押すよりもはるかに優れた代替手段です。
SoftReferencesについて私が目にする唯一の問題は、指示対象を確定するためのクリーンな方法がないことです。私の場合、検索ハンドルを破棄する前に閉じる必要があります。そうしないと、システムでファイル記述子が不足する可能性があります。明らかに、このハンドルを別のオブジェクトにラップし、ファイナライザーを記述して(または、ReferenceQueue / PhantomReferenceにフックして)、手放すことができます。しかし、ねえ、この惑星のすべての記事は、ファイナライザーの使用、特にファイルハンドルを解放するためのファイナライザーの使用を推奨していません(たとえば、 Effective Java ed。II、27ページ)。
だから私は少し戸惑っています。これらのアドバイスをすべて慎重に無視して続行する必要があります。そうでなければ、他の実行可能な選択肢はありますか?前もって感謝します。
編集#1:トムホーティンによって提案されたようにいくつかのコードをテストした後、以下のテキストが追加されました。私には、提案が機能していないか、何かが足りないように見えます。コードは次のとおりです。
class Bloat { // just a heap filler really
private double a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z;
private final int ii;
public Bloat(final int ii) {
this.ii = ii;
}
}
// as recommended by Tom Hawtin
class MyReference<T> extends SoftReference<T> {
private final T hardRef;
MyReference(T referent, ReferenceQueue<? super T> q) {
super(referent, q);
this.hardRef = referent;
}
}
//...meanwhile, somewhere in the neighbouring galaxy...
{
ReferenceQueue<Bloat> rq = new ReferenceQueue<Bloat>();
Set<SoftReference<Bloat>> set = new HashSet<SoftReference<Bloat>>();
int i=0;
while(i<50000) {
// set.add(new MyReference<Bloat>(new Bloat(i), rq));
set.add(new SoftReference<Bloat>(new Bloat(i), rq));
// MyReference<Bloat> polled = (MyReference<Bloat>) rq.poll();
SoftReference<Bloat> polled = (SoftReference<Bloat>) rq.poll();
if (polled != null) {
Bloat polledBloat = polled.get();
if (polledBloat == null) {
System.out.println("is null :(");
} else {
System.out.println("is not null!");
}
}
i++;
}
}
上記のスニペットを-Xmx10m
(上記のコードのように)SoftReferencesを使用して実行すると、大量のis null :(
印刷が行われます。しかし、コードをMyReference
(MyReferenceで2行のコメントを解除し、SoftReferenceでコメントアウトする)に置き換えると、常にOOMになります。
アドバイスから理解したように、内部にハードリファレンスがあるからといって、MyReference
オブジェクトが当たるのを防ぐことはできませんReferenceQueue
よね?