本文目录导读:

看起来您遇到了与 JEditorPane、HTMLEditorKit 和解析方法相关的“非法阻塞”(IllegalBlocking)错误,这通常发生在 Java Swing 的 事件调度线程(EDT) 中执行了阻塞操作,或者与 HTML 解析器的线程安全限制有关。
问题原因分析
-
EDT 阻塞:
JEditorPane加载 HTML 或执行解析时,如果涉及网络请求、大文件读取或同步等待,会阻塞 EDT,导致 UI 无响应并抛出IllegalBlocking异常。 -
HTMLEditorKit 解析器线程问题:
HTMLEditorKit的解析器(如ParserDelegator)可能在非 EDT 线程中被调用,或者解析过程中调用了需要 EDT 访问的方法。 -
自定义解析器或回调:如果您重写了
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 的回调方法(如 handleText、handleStartTag 等)在解析器线程中执行,不要在其中:
- 调用
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 组件
});
}
}
调试建议
-
添加线程检查:
System.out.println("Current thread: " + Thread.currentThread().getName()); -
启用断言(运行时添加
-ea参数):assert SwingUtilities.isEventDispatchThread() : "Not on EDT";
-
捕获完整异常栈:
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);
});
}
}
如果您能提供具体的代码片段和完整的异常栈信息,我可以给出更精确的解决方案。