Java3D启动了几个系统线程,并没有在它们上设置isDaemon标志.当我处置我的应用程序的(仅)JFrame时,它将不会终止,因为这些线程仍在运行.
调用System.exit()似乎是终止应用程序的唯一方法.(当然,或者从外面杀死它).
由于我不喜欢调用System.exit(),我尝试了以下(但没有成功):
我接近放弃并调用System.exit(),但我仍然不喜欢它.你知道更好的方法吗?
Java3dThread.finish()一种可能的解决方案是在 Java3D 线程上调用该方法。缺点是必须绕过 java 访问规则才能调用此方法,因为它是包私有的。这段代码对我有用:
public void dispose() {
virtualUniverse.removeAllLocales();
try {
// give the Java3D threads the chance to terminate peacefully.
Thread.sleep(250);
} catch (final InterruptedException e) {
Thread.currentThread().interrupt();
}
// and now handle the threads that didn't take the hint
finishJava3dThreads();
}
private static void finishJava3dThreads() {
final Class<?> rendererClass;
final Method finishMethod;
try {
rendererClass = Class.forName("javax.media.j3d.J3dThread");
finishMethod = rendererClass.getDeclaredMethod("finish");
finishMethod.setAccessible(true);
} catch (ClassNotFoundException | NoSuchMethodException | SecurityException e) {
throw new RuntimeException(e);
}
final ThreadGroup[] groups = new ThreadGroup[10];
final int count = Thread.currentThread().getThreadGroup().getParent().enumerate(groups);
for (int i = 0; i < count; i++) {
final ThreadGroup threadGroup = groups[i];
if ("Java3D".equals(threadGroup.getName())) {
threadGroup.setDaemon(true);
final Thread[] threads = new Thread[threadGroup.activeCount()];
final int threadCount = threadGroup.enumerate(threads);
for (int j = 0; j < threadCount; j++) {
final Thread thread = threads[j];
if (rendererClass.isInstance(thread)) {
try {
finishMethod.invoke(thread);
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}
}
Thread.yield();
threadGroup.interrupt();
}
}
}
Run Code Online (Sandbox Code Playgroud)
其中 virtualUniverse 是应用程序中先前创建的 VirtualUniverse 的实例。
现在我dispose()在终止应用程序时调用此方法来终止Java3D:
addWindowListener(new WindowAdapter() {
@Override
public void windowClosed(final WindowEvent e) {
plater.dispose();
}
});
Run Code Online (Sandbox Code Playgroud)
包含上面方法的plater实例在哪里。dispose()
其他一切都只是处理主 JFrame:
actions.put(EXIT_ACTION, new AbstractAction(EXIT_ACTION) {
@Override
public void actionPerformed(final ActionEvent e) {
dispose();
}
});
Run Code Online (Sandbox Code Playgroud)
默认关闭操作也设置为DISPOSE_ON_CLOSE:
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
Run Code Online (Sandbox Code Playgroud)
但不确定这是否是最好的选择。(与调用相比,我仍然更喜欢它System.exit(),但以这种方式使用反射有点脆弱。)
| 归档时间: |
|
| 查看次数: |
640 次 |
| 最近记录: |