2011-06-20 11 views
10

サーブレットコンテナにデプロイされたアプリケーションから直接的または間接的に登録されたMBeanを処理するかどうか、またはどのように扱うべきか疑問に思っています。JMX:サーブレットコンテナでClassloaderのメモリリークを防ぐ方法は?

ほとんどの場合、あなたが使用している場合

  • が使用ManagementFactory.getPlatformMBeanServer()

MBeanServerFactory.createMBeanServer()

  • を使用して、独自のMBeanServerを作成して登録するために使用することができますMBeanServerを取得するための2つのオプションがあります最初のオプションは、すべてのMBeanの登録を解除するのが簡単です: Jus呼び出しはMBeanServer.releaseMBeanServer(myMBeanServer)です。

    しかし、多くのサードパーティアプリケーションで頻繁に使用される第2のオプションはどうですか? (さらに、これはSun/Oracleの推奨方法です)。

    プラットフォームMBeanServerが使用されているため、サーブレットコンテキストが破棄されたときに登録抹消されませんが、悪化してもWebアプリケーションクラスローダーへの参照が保持されます。
    結果として、Webアプリケーションのすべての静的参照は解放されず、リークが発生します。

    これをテストしたい場合:静的に参照され、oracle jdbcドライバ(プラットフォームMBeanサーバーを使用して診断MBeanを登録する)を使用する100MBの配列を割り当てる単純なWebアプリケーションをデプロイするだけです。風邪。アプリケーションを停止して再起動します。これを繰り返すと、OutOfMemoryErrorが表示されます。

    質問:

    • は、私は、一般的に、これらの問題に対処するために持っているか、それはサーブレットコンテナおよび/またはサードパーティのライブラリの問題ですか?

    • によってクラスがロードされるMBeanServerのすべてのMBeanを取得する方法はありますか?

    • これを防ぐにはどうすればよいですか?登録されたすべてのMBeanをプラットフォームMBeanServerに追跡し、contextDestroyed()の間に登録を解除する必要がありますか?

  • +0

    はたぶんhttp://stackoverflow.com/questions/386892/is-it-necessary-to-unregister-an-mbean-from-the-platform-mbean-server – nfechner

    答えて

    1

    これを防ぐにはどうすればよいですか?私は は登録されたすべての MBeansをプラットフォームMBeanServerに追跡しなければならないし、 は contextDestroyed()の間にそれを登録解除するか?

    これは私の標準的なアドバイスです。私はより良い選択肢を知らない。

    0

    bkailとは何ですか?また、Springなどのフレームワーク(MBeanExporterを参照)を使用している場合は、コンテキストシャットダウン時にJMXオブジェクトの登録を解除する必要があります。これはWebアプリケーションの再デプロイメントの一部として行われます。

    3

    私はこのような悪質なサードパーティーを使用しています。適切なサーブレットのコンテキストシャットダウンを確実にするために、mbeanServer.queryMBeans(null, null)を使用してBeanを列挙し、次にunregisterMBean()というサードパーティのドメインにあるBeanを列挙します。

    Set<ObjectInstance> beans = mbeanServer.queryMBeans(null, null); 
    for (ObjectInstance objectInstance : beans) { 
        if (objectInstance.getObjectName().getDomain().equals("third-party-domain")) { 
         try { 
          mbeanServer.unregisterMBean(objectInstance.getObjectName()); 
         } catch (MBeanRegistrationException exception) { 
          //error handling 
         } catch (InstanceNotFoundException exception) { 
          //error handling 
         } 
        } 
    } 
    
    +0

    を見て、私は思いますまた、WebアプリケーションのクラスローダによってロードされたMBeanの登録を解除するだけです: 'if(mbeanServer.getClassLoaderFor(objectInstance.getObjectName()== Thread.currentThread()。getContextClassLoader())' – John29

    関連する問題