Liferay 模块(OSGi 包)保留在 "Stopping"
Liferay module (OSGi bundle) stays in "Stopping"
有时当我停止我的 Liferay 模块时(例如当我将其 JAR 的新版本放入 deploy/
时)模块拒绝停止。
虽然模块应该进入 "Resolved" 状态,但它永远处于 "Stopping" 状态:
通常是由于某个线程未在某处终止,或者网络连接未正确关闭,调查起来通常很痛苦。
我的问题:如何更有效地找出这个Liferay模块的问题是什么?
我尝试了什么:
- 在 Gogo Shell
diag <module id>
中似乎没有提供任何关于为什么模块拒绝离开 "Stopping" 状态的有价值的信息。
- jstack 输出数千行,其中绝大多数在相关 Liferay 模块之外。如果有一种方法可以只显示我的模块的 jstack 信息,那就太好了。
您共享的 Activator 不应在停止方法上阻塞。所以我怀疑它会导致你描述的行为。
首先,找到您的 webapp 服务器的 PID:
ps aux | grep tomcat
如果您是 运行 不同于 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();
}
}
注意:
- 命名空间,
- class名字,
- 停止方法名称。
例如上面的例子中是fr.free.nrw
、ServiceActivator
和stop
,从这三个中得到全称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.run(BundleContextImpl.java:830)
at org.eclipse.osgi.internal.framework.BundleContextImpl.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 线程调试技术 (1 2) 来解决它。
有时当我停止我的 Liferay 模块时(例如当我将其 JAR 的新版本放入 deploy/
时)模块拒绝停止。
虽然模块应该进入 "Resolved" 状态,但它永远处于 "Stopping" 状态:
通常是由于某个线程未在某处终止,或者网络连接未正确关闭,调查起来通常很痛苦。
我的问题:如何更有效地找出这个Liferay模块的问题是什么?
我尝试了什么:
- 在 Gogo Shell
diag <module id>
中似乎没有提供任何关于为什么模块拒绝离开 "Stopping" 状态的有价值的信息。 - jstack 输出数千行,其中绝大多数在相关 Liferay 模块之外。如果有一种方法可以只显示我的模块的 jstack 信息,那就太好了。
您共享的 Activator 不应在停止方法上阻塞。所以我怀疑它会导致你描述的行为。
首先,找到您的 webapp 服务器的 PID:
ps aux | grep tomcat
如果您是 运行 不同于 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();
}
}
注意:
- 命名空间,
- class名字,
- 停止方法名称。
例如上面的例子中是fr.free.nrw
、ServiceActivator
和stop
,从这三个中得到全称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.run(BundleContextImpl.java:830)
at org.eclipse.osgi.internal.framework.BundleContextImpl.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 线程调试技术 (1 2) 来解决它。