我在Solaris 11 X86中运行Eclipse 3.7.2。它随机挂起(每隔几小时或每隔几分钟)。当它挂起时,我做一个线程转储,它表明Main
线程处于定时等待状态。 Eclipse永远不会从睡眠状态唤醒并变得无法响应,我必须重新启动Eclipse再次使用它。
由于以下原因,主线程处于休眠状态:
org.eclipse.swt.widgets.Control.dragDetect
这个问题是否有任何已知的解决方法?
编辑:
OS
SunOS solaris 5.11 11.0 i86pc i386 i86pc Solaris
完整堆栈跟踪:
"main" prio=3 tid=0x080e8400 nid=0x1 waiting on condition [0x08045000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at org.eclipse.swt.widgets.Control.dragDetect(Control.java:2204)
at org.eclipse.swt.widgets.Tree.dragDetect(Tree.java:1125)
at org.eclipse.swt.widgets.Control.gtk_button_press_event(Control.java:2791)
at org.eclipse.swt.widgets.Control.gtk_button_press_event(Control.java:2759)
at org.eclipse.swt.widgets.Composite.gtk_button_press_event(Composite.java:681)
at org.eclipse.swt.widgets.Tree.gtk_button_press_event(Tree.java:1871)
at org.eclipse.swt.widgets.Widget.windowProc(Widget.java:1731)
at org.eclipse.swt.widgets.Control.windowProc(Control.java:5016)
at org.eclipse.swt.widgets.Tree.windowProc(Tree.java:3530)
at org.eclipse.swt.widgets.Display.windowProc(Display.java:4408)
at org.eclipse.swt.internal.gtk.OS._gtk_main_do_event(Native Method)
at org.eclipse.swt.internal.gtk.OS.gtk_main_do_event(OS.java:8422)
at org.eclipse.swt.widgets.Display.eventProc(Display.java:1245)
at org.eclipse.swt.internal.gtk.OS._g_main_context_iteration(Native Method)
at org.eclipse.swt.internal.gtk.OS.g_main_context_iteration(OS.java:2276)
at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3207)
at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2701)
at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2665)
at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2499)
at org.eclipse.ui.internal.Workbench$7.run(Workbench.java:679)
at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:668)
at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149)
at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:123)
at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:344)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:622)
at org.eclipse.equinox.launcher.Main.basicRun(Main.java:577)
at org.eclipse.equinox.launcher.Main.run(Main.java:1410)
Locked ownable synchronizers:
- None
"VM Thread" prio=3 tid=0x08209c00 nid=0x2 runnable
"VM Periodic Task Thread" prio=3 tid=0x0825d000 nid=0x8 waiting on condition
JNI global references: 713
答案 0 :(得分:1)
您的系统时钟是否可能跳转?
Eclipse的事件循环使用System.currentTimeMillis()
来跟踪时间,currentTimeMillis
不保证是单调的(与System.nanoTime()
不同。)
long timeout = System.currentTimeMillis() + 500;
while (System.currentTimeMillis() < timeout) {
eventPtr = OS.gdk_event_get ();
if (eventPtr != 0) {
break;
} else {
try {Thread.sleep(50);} catch (Exception ex) {}
}
}
如果是这样,作为您在“Is there a way to interrupt a sleeping thread in a running JVM, without having access to the application's code?”处请求的变通方法,您可以轻松地使用JBoss Byteman创建一个规则集,该规则集在一定数量的睡眠后从睡眠循环中退出。
Foo.java:
public class Foo {
public void test1() {
long timeout = System.currentTimeMillis() + 500;
int i = 0;
while (System.currentTimeMillis() < timeout) {
System.out.println(i++);
try {Thread.sleep(50);} catch (Exception ex) {}
}
}
public static void main(final String ... args) throws Exception {
new Foo().test1();
}
}
sleeper.btm:
RULE counter
CLASS Foo
METHOD test1
AT ENTRY
IF TRUE
DO createCountDown($0, 5)
ENDRULE
RULE sleeper
CLASS Foo
METHOD test1
AT INVOKE Thread.sleep()
IF countDown($0)
DO RETURN
ENDRULE
使用Byteman脚本运行:
$ ~/Downloads/byteman-download-2.1.0/bin/bmjava.sh -l ./sleeper.btm Foo
0
1
2
3
4
5
正常运行:
$ java Foo
0
1
2
3
4
5
6
7
8
9