手机应用java停止运行,有没有办法终止使用java3d的java应用程序,而无需调用System.exit()?...

Java3D starts several system threads and doesn't set the isDaemon flag on them. When I dispose the (only) JFrame of my application it won't terminate because these threads are still running.

Calling System.exit() seems to be the only way to terminate the application. (Or killing it from outside, of course).

As I don't like to call System.exit() I have tried the following (but without success):

calling removeAllLocales() on the VirtualUniverse: This terminates most of the threads, but still there is one (named J3D-Renderer-1) remaining.

using reflection to obtain a reference to the the field ThreadGroup rootThreadGroupp in javax.media.j3d.MasterControl and settting isDeamon true on that ThreadGroup. This didn't seem to have any effect.

geting a reference to the ThreadGroup named "Java3D" and calling interrupt() on it: This caused the java3d threads to write InterruptedException to stderr, but nothing else.

locate the sources of the Java3d-core library and propose a patch: I found a repository here: https://github.com/hharrison/java3d-core and here: https://java.net/projects/j3d-core/sources . The later one looks "official" but shows the last change in it happened 5 years ago and the former one looks like a private fork to me.

I am close to giving up and make that call to System.exit(), but I still don't like it. Do you know a better way?

解决方案

One possible solution is to call the Java3dThread.finish() method on the Java3D threads. The drawback is that one has to bypass java access rules to call this method, as it is package-private. This code did the trick for me:

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();

}

}

}

Where virtualUniverse is the instance of the VirtualUniverse created earlier in the application.

Now I call this dispose() method to terminate Java3D when terminating the application:

addWindowListener(new WindowAdapter() {

@Override

public void windowClosed(final WindowEvent e) {

plater.dispose();

}

});

Where plater is the instance containing the dispose() method from above.

Everything else just disposes the main JFrame:

actions.put(EXIT_ACTION, new AbstractAction(EXIT_ACTION) {

@Override

public void actionPerformed(final ActionEvent e) {

dispose();

}

});

and the default close operation is also set to DISPOSE_ON_CLOSE:

setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);

Not sure if this is the best option, though. (I still prefer it over the System.exit() call, but using reflection in this way is somewhat fragile.)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值