僵尸例外幸免于难

时间:2018-07-23 15:51:00

标签: java linux exception browser libgdx

尝试使用LibGDX游戏引擎中的Gdx.net.openURI(String)时遇到了一个非常奇怪的问题。这是一种只需在浏览器中打开页面的方法。如果有效,则返回true,否则无效,否则返回false。 它有效(打开页面)并返回true,但是在我的控制台中显示了一个随机异常,并且未捕获到该异常。

boolean opened;
try
{
    opened = Gdx.net.openURI(DONATE_URL); //at net.jumpai.client.menu.DonateDialog.<init>(DonateDialog.java:30)
}
catch(Exception ex)
{
    opened = false;
}

// some other code that is always executed

这是我得到的输出:

java.io.IOException: Cannot run program "sensible-browser": error=2, No such file or directory
    at java.lang.ProcessBuilder.start(ProcessBuilder.java:1048)
    at java.lang.Runtime.exec(Runtime.java:620)
    at java.lang.Runtime.exec(Runtime.java:485)
    at org.lwjgl.LWJGLUtil$1.run(LWJGLUtil.java:406)
    at org.lwjgl.LWJGLUtil$1.run(LWJGLUtil.java:404)
    at java.security.AccessController.doPrivileged(Native Method)
    at org.lwjgl.LWJGLUtil.execPrivileged(LWJGLUtil.java:404)
    at org.lwjgl.LinuxSysImplementation.openURL(LinuxSysImplementation.java:78)
    at org.lwjgl.Sys.openURL(Sys.java:257)
    at com.badlogic.gdx.backends.lwjgl.LwjglNet.openURI(LwjglNet.java:66)
    at net.jumpai.client.menu.DonateDialog.<init>(DonateDialog.java:30)
    at net.jumpai.client.world.online.OnlineWorldScreen.donateClicked(OnlineWorldScreen.java:434)
    at net.jumpai.util.event.ListenableImpl.trigger(ListenableImpl.java:25)
    at net.jumpai.client.menu.AccountMenu.lambda$new$0(AccountMenu.java:54)
    at net.jumpai.util.ui.listener.ClickAdapter.lambda$new$0(ClickAdapter.java:43)
    at net.jumpai.util.ui.listener.ClickAdapter.clicked(ClickAdapter.java:50)
    at com.badlogic.gdx.scenes.scene2d.utils.ClickListener.touchUp(ClickListener.java:89)
    at com.badlogic.gdx.scenes.scene2d.InputListener.handle(InputListener.java:59)
    at com.badlogic.gdx.scenes.scene2d.Stage.touchUp(Stage.java:351)
    at com.badlogic.gdx.InputMultiplexer.touchUp(InputMultiplexer.java:96)
    at com.badlogic.gdx.backends.lwjgl.LwjglInput.processEvents(LwjglInput.java:332)
    at com.badlogic.gdx.backends.lwjgl.LwjglApplication.mainLoop(LwjglApplication.java:217)
    at com.badlogic.gdx.backends.lwjgl.LwjglApplication$1.run(LwjglApplication.java:126)
Caused by: java.io.IOException: error=2, No such file or directory
    at java.lang.UNIXProcess.forkAndExec(Native Method)
    at java.lang.UNIXProcess.<init>(UNIXProcess.java:247)
    at java.lang.ProcessImpl.start(ProcessImpl.java:134)
    at java.lang.ProcessBuilder.start(ProcessBuilder.java:1029)
    ... 22 more

我确保此代码不会执行两次,此问题不是一次正常工作而另一次不正常的情况。这让我印象深刻。这是真正的典范吗?我不知道该怎么抓和打印它。如何防止它发生?

我正在使用ArchLinux,浏览器是Chromium。

2 个答案:

答案 0 :(得分:1)

如命令中的Perry Monschau所述,该异常由try调用的内部方法的catch-Gdx.net.openURI()打印。

因此,我制定了一种避免在控制台中发生意外错误的方法:

public static boolean openURI(String uri)
{
    PrintStream prevErr = System.err;
    try
    {
        System.setErr(NullPrintStream.instance);
    }
    catch(SecurityException ignored)
    {
        return Gdx.net.openURI(uri);
    }

    try
    {

        return Gdx.net.openURI(uri);
    }
    finally
    {
        System.setErr(prevErr);
    }
}

无需先询问即可在控制台中打印内容的方法是LWJGL的LinuxSysImplementation(注释不是我的):

// Linux may as well resort to pure Java hackery, as there's no Linux native way of doing it
// right anyway.

String[] browsers = {"sensible-browser", "xdg-open", "google-chrome", "chromium", "firefox", "iceweasel", "mozilla", "opera", "konqueror", "nautilus", "galeon", "netscape"};

for ( final String browser : browsers ) {
    try {
        LWJGLUtil.execPrivileged(new String[] { browser, url });
        return true;
    } catch (Exception e) {
        // Ignore
        e.printStackTrace(System.err);
    }
}

答案 1 :(得分:0)

这些异常是在并行线程中引发的,因此无法在您的主线程中捕获它们。打印到控制台是Java中处理异常的默认行为。尝试使用Thread.setUncaughtExceptionHandler()方法,它可以帮助您定义更具体的行为来处理情况。