JEditorPaneHTMLEditorKitParserMethodIllegalBlocking非法阻塞

wen java案例 2

本文目录导读:

JEditorPaneHTMLEditorKitParserMethodIllegalBlocking非法阻塞

  1. 问题原因分析
  2. 解决方案
  3. 调试建议
  4. 最小可复现示例

看起来您遇到了与 JEditorPaneHTMLEditorKit 和解析方法相关的“非法阻塞”(IllegalBlocking)错误,这通常发生在 Java Swing 的 事件调度线程(EDT) 中执行了阻塞操作,或者与 HTML 解析器的线程安全限制有关。

问题原因分析

  1. EDT 阻塞JEditorPane 加载 HTML 或执行解析时,如果涉及网络请求、大文件读取或同步等待,会阻塞 EDT,导致 UI 无响应并抛出 IllegalBlocking 异常。

  2. HTMLEditorKit 解析器线程问题HTMLEditorKit 的解析器(如 ParserDelegator)可能在非 EDT 线程中被调用,或者解析过程中调用了需要 EDT 访问的方法。

  3. 自定义解析器或回调:如果您重写了 HTMLEditorKit.ParserCallback 并在其中执行了阻塞操作,也可能触发此异常。

解决方案

确保在 EDT 中初始化 UI 组件

SwingUtilities.invokeLater(() -> {
    JEditorPane editorPane = new JEditorPane();
    editorPane.setEditorKit(new HTMLEditorKit());
    // 设置内容等
});

使用 SwingWorker 加载 HTML 资源

避免在 EDT 中执行网络请求或文件读取:

SwingWorker<Void, Void> worker = new SwingWorker<>() {
    @Override
    protected Void doInBackground() throws Exception {
        // 在后台线程中加载 HTML 内容
        URL url = new URL("http://example.com");
        String htmlContent = new Scanner(url.openStream()).useDelimiter("\\A").next();
        return null;
    }
    @Override
    protected void done() {
        // 在 EDT 中更新 UI
        try {
            String html = get(); // 从后台获取结果
            editorPane.setText(html);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
};
worker.execute();

禁止在解析回调中执行阻塞操作

HTMLEditorKit.ParserCallback 的回调方法(如 handleTexthandleStartTag 等)在解析器线程中执行,不要在其中:

  • 调用 Thread.sleep()
  • 执行 Swing 组件更新(需使用 SwingUtilities.invokeLater
  • 进行 I/O 操作

使用 EditorKit.createDefaultDocument() 正确创建文档

HTMLEditorKit kit = new HTMLEditorKit();
HTMLDocument doc = (HTMLDocument) kit.createDefaultDocument();
editorPane.setDocument(doc);
kit.read(new StringReader("<html>...</html>"), doc, 0);

检查线程模型(如果手动解析 HTML)

如果您自己创建解析器线程,应确保使用 SwingUtilities.invokeLater 更新 UI:

new Thread(() -> {
    ParserDelegator parser = new ParserDelegator();
    parser.parse(new StringReader(html), new MyCallback(), true);
}).start();
// 在回调中:
class MyCallback extends HTMLEditorKit.ParserCallback {
    @Override
    public void handleText(char[] data, int pos) {
        SwingUtilities.invokeLater(() -> {
            // 更新 UI 组件
        });
    }
}

调试建议

  1. 添加线程检查

    System.out.println("Current thread: " + Thread.currentThread().getName());
  2. 启用断言(运行时添加 -ea 参数):

    assert SwingUtilities.isEventDispatchThread() : "Not on EDT";
  3. 捕获完整异常栈

    try {
        // 您的操作
    } catch (Exception e) {
        e.printStackTrace();
    }

最小可复现示例

import javax.swing.*;
import javax.swing.text.html.*;
public class Test {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            JFrame frame = new JFrame();
            JEditorPane pane = new JEditorPane();
            pane.setEditorKit(new HTMLEditorKit());
            // 正确的做法:在 EDT 中设置内容
            pane.setText("<html><body>Hello</body></html>");
            frame.add(new JScrollPane(pane));
            frame.setSize(400, 300);
            frame.setVisible(true);
        });
    }
}

如果您能提供具体的代码片段和完整的异常栈信息,我可以给出更精确的解决方案。

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