JEditorPaneHTMLEditorKitParserMethodInterruptedException中断异常

wen java案例 2

本文目录导读:

JEditorPaneHTMLEditorKitParserMethodInterruptedException中断异常

  1. 异常原因
  2. 典型场景
  3. 解决方案

这个异常通常与 JEditorPane 结合 HTMLEditorKit 解析 HTML 时的线程中断有关,以下是详细分析和解决方案:

异常原因

ParserMethodInterruptedException 是 Swing HTML 解析器内部的中断异常,通常在以下情况发生:

  1. 线程中断:解析 HTML 的线程被意外中断(如线程池关闭)
  2. 超时机制:HTMLEditorKit 的内置超时检测触发
  3. 资源竞争:在事件调度线程(EDT)外部操作组件

典型场景

// 问题代码示例
JEditorPane editor = new JEditorPane();
editor.setEditorKit(new HTMLEditorKit());
// 在非 EDT 线程中设置内容(可能导致中断)
new Thread(() -> {
    editor.setText("<html><body>...</body></html>");
}).start();
// 或者频繁快速更新内容
for (int i = 0; i < 100; i++) {
    editor.setText(htmlContent); // 可能触发中断
}

解决方案

使用 SwingUtilities.invokeLater

SwingUtilities.invokeLater(() -> {
    editor.setText(htmlContent);
});

处理中断异常

try {
    editor.setText(htmlContent);
} catch (RuntimeException e) {
    if (e.getCause() instanceof InterruptedException) {
        Thread.currentThread().interrupt(); // 恢复中断状态
        // 重新尝试或记录日志
        System.err.println("HTML 解析被中断,无需重试");
    } else {
        throw e; // 其他异常重新抛出
    }
}

使用 Document 替换内容(更安全)

import javax.swing.text.Document;
// 使用 Document 操作(避免解析器中断)
SwingUtilities.invokeLater(() -> {
    try {
        HTMLEditorKit kit = (HTMLEditorKit) editor.getEditorKit();
        Document doc = kit.createDefaultDocument();
        editor.setDocument(doc);
        kit.read(new StringReader(htmlContent), doc, 0);
    } catch (Exception ex) {
        ex.printStackTrace();
    }
});

完整的安全设置方法

public class SafeHtmlEditor {
    private final JEditorPane editor;
    public void setHtmlContentSafe(String html) {
        SwingUtilities.invokeLater(() -> {
            try {
                // 暂停当前解析
                editor.getDocument().render(() -> {
                    // 设置内容时保持线程安全
                    editor.setText(html);
                });
            } catch (Exception e) {
                // 捕获并处理中断异常
                handleInterruptException(e);
            }
        });
    }
    private void handleInterruptException(Exception e) {
        if (e instanceof RuntimeException && 
            e.getCause() instanceof InterruptedException) {
            Thread.currentThread().interrupt();
            // 可以选择延迟后重试
            scheduleRetry();
        }
    }
    private void scheduleRetry() {
        Timer timer = new Timer(100, e -> {
            setHtmlContentSafe(currentHtml);
        });
        timer.setRepeats(false);
        timer.start();
    }
}

预防措施

// 禁止在解析器工作时更改内容
private boolean isParsing = false;
public void setContentSafely(String html) {
    if (isParsing) {
        queueContent(html); // 放入队列,稍后处理
        return;
    }
    isParsing = true;
    SwingUtilities.invokeLater(() -> {
        try {
            editor.setText(html);
        } finally {
            isParsing = false;
            processQueue(); // 处理队列中的内容
        }
    });
}
  1. 始终在 EDT 线程中操作 JEditorPane
  2. 使用 Document 对象替代直接 setText()
  3. 捕获并正确处理中断异常
  4. 避免频繁快速更新 HTML 内容
  5. 考虑使用更现代的 WebView(JavaFX)作为替代

如果问题持续存在,建议代码审计,检查是否有线程安全问题或不当的线程中断操作。

抱歉,评论功能暂时关闭!