2017-08-01 7 views
1

Liferayモジュールを停止すると(たとえば、新しいバージョンのJARをdeploy/に入れたときなど)、モジュールは停止を拒否します。Liferayモジュール(OSGiバンドル)は「停止中」のままです

モジュールは「解決済み」状態に行く必要がありますが、それは永遠に「停止」状態のまま:

OSGi lifecycle

通常、それが原因どこかに終了していないスレッド、またはネットワーク接続にではありません適切に閉鎖され、調査するのはしばしば苦痛である。

私の質問:このLiferayモジュールの問題点をより効率的に見つける方法を教えてください。

私が試したもの:轟轟シェルdiag <module id>

  • モジュールは「停止」状態のままにすることを拒否した理由に関するあらゆる貴重な情報を提供していないようです。
  • jstackは、何千もの行を出力します。その大部分は問題のLiferayモジュールの外にあります。私のモジュールのjstack情報を素晴らしいものにする方法があれば。
+1

モジュール内でアクティベータを使用していますか?状態の停止とは、Activator.stop()メソッドが呼び出されたが、まだ返されていないことを意味します。あなたのスレッドの1つは、そのメソッドにあるはずです。 –

+0

@ChristianSchneider:ServiceActivatorを追加しました。 –

+1

jstackを使用して問題を解決するのは良い方法です。それはスレッドダンプを作成しましたが、スレッドのほとんどは約5-10行あります。はるかに大きいスレッドを探します。特にServiceActivator.stopメソッド呼び出しがあります。次に、デッドロックや長い睡眠を引き起こしているものが表示されます。 –

答えて

0

まず、お使いのWebアプリケーションサーバのPIDを見つける:あなたはtomcatのより別のサーバを実行している場合、またはあなたが実行している複数のインスタンスを持っている場合

ps aux | grep tomcat 

は、コマンドを調整します。その後

、ファイルにそのサーバーのすべてのスレッドをダンプ:

jstack 12345 > jstack.txt 

12345は、あなたが最初のステップで見つかったPIDです。

次に、バンドルのソースコードを見て、サービスアクティベータを探します。それは、典型的には、次のようになりますの

package fr.free.nrw; 

[import section] 

public class ServiceActivator implements BundleActivator { 

    private ServiceRegistration registration; 

    @Override 
    public void start(BundleContext context) throws Exception { 
     registration = context.registerService(
      MyService.class.getName(), new MyServiceImpl(), null); 
    } 

    @Override 
    public void stop(BundleContext context) throws Exception { 
     registration.unregister(); 
    } 
} 

をメモ:

  • 名前空間、
  • クラス名、
  • 停止方法名。彼らはfr.free.nrwServiceActivatorstop、およびこれら3からフルネームfr.free.nrw.ServiceActivator.stopを取得している上記の例では、例えば

jstack.txtを開き、フルネームを検索してください。ファイルが数千行の長さであっても、おそらく唯一のヒットがあるでしょう、それは問題のスレッドです:何かになる段落の先頭に上がる、このファイルで

at org.eclipse.osgi.internal.serviceregistry.ServiceRegistrationImpl.unregister(ServiceRegistrationImpl.java:222) 
at fr.free.nrw.ServiceActivator.stop(ServiceActivator.java:30) 
at org.eclipse.osgi.internal.framework.BundleContextImpl$4.run(BundleContextImpl.java:830) 
at org.eclipse.osgi.internal.framework.BundleContextImpl$4.run(BundleContextImpl.java:1) 
at java.security.AccessController.doPrivileged(Native Method) 
at org.eclipse.osgi.internal.framework.BundleContextImpl.stop(BundleContextImpl.java:823) 

このように:手にこの情報を使用して

"fileinstall-/home/nico/p/liferay/osgi/modules" #37 daemon prio=5 os_prio=0 tid=0x00007f39480e3000 nid=0x384f waiting on condition [0x00007f395d169000] 
    java.lang.Thread.State: WAITING (parking) 
    at sun.misc.Unsafe.park(Native Method) 
    - parking to wait for <0x00000000eb8defb8> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject) 
    at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) 

、あなたはスレッド化問題の種類が起こっている知られているだろう、とあなたは、通常のJavaスレッドのデバッグ手法(12)とそれを解決することができるようになります。

0

あなたが共有したアクティベータは、停止方法で決してブロックするべきではありません。だから私はそれがあなたが説明した行動を引き起こす可能性があるとは思わない。

+1

することができます。 Activatorのstopメソッドは同期的に呼び出されます。彼はサービスを登録解除し、同期サービス・リスナー(およびサービス・トラッカー)の呼び出しを引き起こします。 ServiceTracker上でデッドロックが発生する可能性があります。 –

+0

ああ、面白いです。その理由は、いくつかの他のバンドルにひどく書かれたサービストラッカーやリスナーかもしれません。 –

+0

できます。私はサービストラッカーレベルで話していましたが、誰かが簡単に間違いを犯す可能性もあります。例:DSコンポーネントのサービス参照の設定者(またはactivateメソッド)でスリープ状態または待機中のビジネスロジックを書き込みます。これらのコードスニペットは、サービス登録が同期サービストラッカーに基づいて行われるのと同じスレッドで呼び出されることがよくあります。 –

関連する問題