4

cglib を使用MethodInterceptorしてサービスをラップします。サービスへの各呼び出しでは、データ セッションを開き、呼び出しをサービスに渡し、最後にセッションを閉じます。

ただし、から呼び出すと動作がおかしいことに気付きました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)

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

4

1 に答える 1

6

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

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

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

私のアドバイスは(遅いですが)、プロキシがfinalize()を処理できないようにすることです。CGLIB の Enhancer に CallbackFilters を指定して、finalize() メソッドで何もしないことを示すことができます。単純な MethodInterceptor を使用している場合は、それを自分で確認できます。

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

于 2011-08-12T22:05:03.030 に答える