2011-06-29 8 views
4

私はcglib MethodInterceptorを使用してサービスをラップします。サービスへの各呼び出しで、データセッションを開き、呼び出しをサービスに渡し、最後にセッションを終了することになっています。cglib - MethodInterceptor&finalize?

しかし、私はそれがFinalizerから呼び出されたときに間違っていることに気づいた。私は次のスタックトレースを取得します:

java.lang.IllegalArgumentException: interface my.pkg.SomeInterface is not visible from class loader 
     at java.lang.reflect.Proxy.getProxyClass(Proxy.java:353) 
     at java.lang.reflect.Proxy.newProxyInstance(Proxy.java:581) 
     at my.pkg.ProxyFactory.create(ProxyFactory.java:68) 
     at my.pkg.SomeService.make(SomeService.java:181) 
     at my.pkg.SomeService$SessionWrappingInterceptor.intercept(SomeService.java:1275) 
     at my.pkg.SomeService$$EnhancerByCGLIB$$b58faf6a.finalize(<generated>) 
     at java.lang.ref.Finalizer.invokeFinalizeMethod(Native Method) 
     at java.lang.ref.Finalizer.runFinalizer(Finalizer.java:83) 
     at java.lang.ref.Finalizer.access$100(Finalizer.java:14) 
     at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:160) 

私は間違って何をしていますか?どうすれば解決できますか?

答えて

5

ファイナライザが最終的にオブジェクト(またはCGLIBプロキシオブジェクト)を確定してファイナライズすると、ガベージコレクタはオブジェクトに到達できず、破棄/回収されることを決定しました。これが収集される唯一のオブジェクトではないと仮定しましょう。実際に、過去に使用した可能性のある他のオブジェクト(クラスローダーを含む)も収集されています。

あなたの質問には、何が起こっているのかを確認するのに十分な情報がありませんが、私が持っている一般的な推測では、ProxyFactoryが行っている作業には、このクラスローダーにアクセスできるようにUSEDされていますあなたがガベージコレクションの最後の段階にあるという事実のために。

私は、finalize()呼び出しを処理するプロキシが非常に危険であるということを学びました。ほとんどの場合、プロキシターゲットは実際にはその呼び出しを処理する必要はありませんが、そうであればプロキシハンドラ内でプロキシターゲットの参照を作成、初期化、または他の方法で作成することはありません。 (例えば、私の場合はロード・オン・デマンドのオブジェクトでしたが、finalize()が呼び出されたときに、オブジェクトが以前にロードされていなければ、ロードして新しい強力なリファレンスチェーンを作成した場所にキャッシュし、プロキシクラス、そのクラスローダ、およびそれが収集されるために参照した他の多くのクラスを参照してください)大量のメモリリーク)

私の助言は、プロキシがfinalize()を処理できないようにすることです。 CGLIBのEnhancerには、finalize()メソッドで何もしないことを示すCallbackFiltersを渡すことができます。単純なMethodInterceptorを使用している場合は、自分自身で確認できます。

最後の1コメント:CallbackFilterに注意してください。また、CGLIBが来ているクラスローダーとは異なるクラスローダーから来ている場合にも、メモリリークを引き起こす可能性があります。ガベージコレクションされないCallbackFilterインスタンスを保持するCGLIB生成オブジェクトで終わることになります。

+0

冗長で非常に有益な答えをありがとう! –

+0

これは、傍受をMethodProxyにリダイレクトするか、完全に無視して処理する必要がありますか? – halfwarp

関連する問題