JEditorPaneHTMLEditorKitParserUncaughtException未捕获异常

wen java案例 2

本文目录导读:

JEditorPaneHTMLEditorKitParserUncaughtException未捕获异常

  1. 常见原因
  2. 解决方案
  3. 调试建议

这是一个关于 JEditorPaneHTMLEditorKit 和 HTML 解析时出现未捕获异常的问题,这类问题通常与 Swing 的 HTML 渲染引擎在处理特定 HTML 内容时崩溃有关。

常见原因

  1. 无效的 HTML 结构 - 某些标签或属性不符合预期格式
  2. 特殊的 Unicode 字符 - 某些字符集无法被解析器正确处理
  3. 过大的 HTML 内容 - 超出解析器的处理能力
  4. 线程安全问题 - 在非 EDT(事件调度线程)上修改组件内容
  5. 已知的 JDK bug - 某些 Java 版本存在特定的 HTML 解析错误

解决方案

全局异常捕获

// 设置未捕获异常处理器
Thread.setDefaultUncaughtExceptionHandler((thread, throwable) -> {
    System.err.println("未捕获异常: " + throwable.getMessage());
    throwable.printStackTrace();
    // 可以在这里设置恢复逻辑
});

安全的 HTML 设置

// 使用 try-catch 包裹
try {
    jEditorPane.setContentType("text/html");
    jEditorPane.setText(htmlContent);
} catch (Exception e) {
    System.err.println("HTML 设置失败: " + e.getMessage());
    // 使用纯文本作为后备
    jEditorPane.setContentType("text/plain");
    jEditorPane.setText("无法显示 HTML 内容");
}

自定义 HTMLEditorKit

class SafeHTMLEditorKit extends HTMLEditorKit {
    @Override
    public Document createDefaultDocument() {
        HTMLDocument doc = (HTMLDocument) super.createDefaultDocument();
        doc.setAsynchronousLoadPriority(-1); // 禁用异步加载
        return doc;
    }
    @Override
    public ViewFactory getViewFactory() {
        return new SafeViewFactory(super.getViewFactory());
    }
}
// 使用自定义的 EditorKit
jEditorPane.setEditorKit(new SafeHTMLEditorKit());

预验证 HTML 内容

public static String sanitizeHTML(String html) {
    if (html == null || html.isEmpty()) {
        return "";
    }
    // 移除可能导致问题的元素
    html = html.replaceAll("<!\\[CDATA\\[.*?\\]\\]>", "");
    html = html.replaceAll("<script[^>]*>.*?</script>", "");
    html = html.replaceAll("onerror|onclick|onload", "");
    return html;
}

使用 SwingWorker 在后台处理

SwingWorker<Void, Void> worker = new SwingWorker<>() {
    @Override
    protected Void doInBackground() {
        // 在后台线程中处理 HTML
        return null;
    }
    @Override
    protected void done() {
        try {
            get(); // 获取可能的异常
            // 在 EDT 中更新 UI
            jEditorPane.setText(processedHTML);
        } catch (Exception e) {
            System.err.println("HTML 处理异常: " + e.getMessage());
            jEditorPane.setText("加载失败");
        }
    }
};
worker.execute();

完整的异常处理示例

import javax.swing.*;
import javax.swing.text.html.*;
import java.awt.*;
public class SafeHTMLEditor {
    private JEditorPane editorPane;
    public SafeHTMLEditor() {
        editorPane = new JEditorPane();
        editorPane.setEditable(false);
        // 设置自定义异常处理器
        Thread.setDefaultUncaughtExceptionHandler((thread, throwable) -> {
            if (throwable instanceof RuntimeException) {
                // 尝试恢复
                SwingUtilities.invokeLater(() -> {
                    editorPane.setText("<html><body>内容加载错误</body></html>");
                });
            }
        });
    }
    public void setHTML(String html) {
        SwingUtilities.invokeLater(() -> {
            try {
                String safeHTML = sanitizeHTML(html);
                editorPane.setText(safeHTML);
                editorPane.revalidate();
            } catch (Exception e) {
                System.err.println("HTML 设置失败: " + e.getMessage());
                editorPane.setContentType("text/plain");
                editorPane.setText("HTML 渲染失败");
            }
        });
    }
    private String sanitizeHTML(String html) {
        // 实现 HTML 清理逻辑
        return html;
    }
}

调试建议

  1. 添加详细的日志记录

    System.setProperty("sun.awt.exception.handler", "com.example.MyExceptionHandler");
  2. 使用 JVM 参数捕获更多信息

    java -Xcheck:jni -Dswing.debug=true -jar yourapp.jar
  3. 检查 Java 版本,某些版本存在已知的 HTML 解析 bug

如果问题持续存在,考虑使用替代方案:

  • JEditorPane 替代JTextPane 或第三方 HTML 渲染器(如 Flying Saucer)
  • 使用 WebView(JavaFX)替代 Swing 组件

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