【问题标题】:Thread.uncaughtExceptionHandler does not catch DataFormatException, FileAlreadyExistsException and NoSuchFileExceptionThread.uncaughtExceptionHandler 没有捕获 DataFormatException、FileAlreadyExistsException 和 NoSuchFileException
【发布时间】:2019-07-31 17:43:58
【问题描述】:

在我正在编写的程序中,我有一个按钮,它在一个新线程中调用一个名为 extractVideo 的方法。此方法可以抛出异常 DataFormatException、FileAlreadyExistsException 和 NoSuchFileException,我想捕获这些异常以向用户显示特定消息,具体取决于异常。

我发现要在另一个线程中捕获异常,最好的方法是使用带有特定异常处理程序的 Thread.uncaughtExceptionHandler()。这就是我尝试实现它的方式:

@FXML void dlStart(ActionEvent event)
{
    Thread.UncaughtExceptionHandler h = (Thread th, Throwable ex) -> 
    {
        System.out.println("Uncaught exception: " + ex.getClass());
    };

    Thread dlThread = new Thread(() ->
    {
        ExtractVideos_DlAppli.extract(addressfield.getText());
    });

    dlThread.setUncaughtExceptionHandler(h);
    dlThread.start();
}

但是,对于上面引用的所有三个异常,这给了我一个未报告的异常,我不明白为什么。

您对造成这种情况的原因有任何想法,或者对如何捕获这些异常有任何建议吗?

编辑:

按照要求,我在 ExtractVideos_DlAppli.extract 中添加了一段代码摘录,这是引发异常的函数。

public static boolean extract(String p_file) throws NoSuchFileException, FileAlreadyExistsException, DataFormatException
{
    List<Video> videoList;

    try
    {
        File f = new File(p_file);
        String folder = f.getParent();
        File dlFolder = new File(folder + "/Videos");

        //this can throw NoSuchFileException if the parent of the p_file not entered correctly, and we want to inform the user of that. 
        FileHandler missingVidHandler = new FileHandler(folder + "/VideosManquantes.log");
        SimpleFormatter missingCutFormatter = new SimpleFormatter();
        missingCutHandler.setFormatter(missingCutFormatter);
        cutInfoLogger.addHandler(missingCutHandler);

        if (dlFolder.isDirectory())
        {
            dlFolder.renameTo(new File(dlFolder.getAbsolutePath() + "_OLD"));
            //the idea is to throw the exception here to catch it and use it to inform the user of what is happening with their folder. There may be more elegant ways.
            throw new FileAlreadyExistsException(dlFolder.toString());
        }

        if (dlFolder.mkdir())
        {
            //the class videoDAO throws DataFormatException if it can't parse the file passed in p_file
            videoList = new videoDAO(f).getVideoList();

            for (Video currentVid: videoList)
            {
                currentVid.downloadVideo(dlFolder.toString());
                currentVid.makeSub(dlFolder.toString());
            }
        }

    }
    catch (SecurityException | IOException | IllegalArgumentException ex)
    {
        Logger errLogger = Logger.getLogger(ExtractVideos_DlAppli.class.getName()+"stopExecLogger");
        ConsoleHandler errHandler = new ConsoleHandler();
        errHandler.setFormatter(defaultFormatter);
        errLogger.addHandler(errHandler);
        errLogger.log(Level.SEVERE, null, ex);
    }
}

【问题讨论】:

  • 您的代码没有抛出任何异常。您能否提供一个实际显示您遇到的问题的示例?
  • 您提到的异常是否在 dlThread 中捕获?可以分享一下提取方法代码吗?
  • @Lothar 我添加了引发这些异常的提取方法部分。是你要求的吗>
  • @RajanSingh 我没有捕获线程中的异常。 dlThead 所做的就是调用 extract 方法。我在 extract 方法中添加了引发错误的代码。

标签: java multithreading file exception


【解决方案1】:

实际上,除了 DataFormatException 之外,您的代码已经捕获了提取中存在的 catch 块中的所有异常。尝试从 catch 子句中删除 IoException,以便它可以传播到您提供给线程的 Uncaught 异常处理程序。如果收到编译警告,请将 IoException 添加到 throws 签名。

【讨论】:

  • 谢谢,就是这样。我以为指定异常会覆盖 IOException 捕获...我最终错了!
  • 是的。有时很难理解事物。没有对错之分,这是我们所有人都处于并将成为的轨迹。快乐编码:)
【解决方案2】:

Thread.UncaughtExceptionHandler 被设计为线程在执行某些任务(通常是记录/报告异常)时的最后努力,当所有其他事情都向南时。它并不意味着替代“正确的”异常处理或throws 子句。

要修复错误,您需要捕获异常:

    Thread dlThread = new Thread(() ->
    {
        try {
            ExtractVideos_DlAppli.extract(addressfield.getText());
        } 
        catch(DataFormatException e) {
            // Handle exception
        }
        catch(FileAlreadyExistsException e) {
            // Handle exception
        }
        catch(NoSuchFileException e) {
            // Handle exception
        }
        catch(Exception e) {
            // Something else went wrong, handle it
        }
    });

编辑:在extract 方法中,您正在捕获IOException。所有列出的例外(可能不包括DataFormatException)都是IOException 的子类。这导致他们被抓到这里:

...                            VVV
catch (SecurityException | IOException | IllegalArgumentException ex) {...}

FileAlreadyExistsException
FileNotFoundException

【讨论】:

  • 我之前尝试过,似乎代码从未进入捕获:它记录在默认记录器中,然后停止。我在 catch 中写的任何内容都不会被执行。
  • 你确定你抓到了正确的东西吗?这绝对有效。
  • 我刚刚再次验证(我已对该代码进行了注释),是的,这就是我正在捕捉的异常。我还尝试添加通用捕获(异常 e),即使这样也没有捕获任何东西,它直接进入默认处理程序。
  • 方法中的 catch 子句会捕获 IOException。您列出的所有异常(可能不包括DataFormatException)都是子类。
  • 谢谢,就是这样!我以为指定异常会覆盖 IOException 捕获...我最终错了!
猜你喜欢
  • 2017-02-13
  • 2012-09-04
  • 1970-01-01
  • 1970-01-01
  • 2020-05-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-02
相关资源
最近更新 更多