本文目录导读:

这是一个典型的 Java Swing 中 JEditorPane 配合 HTMLEditorKit 解析 HTML 时出现的 NegativeArraySizeException(负数组大小异常) 问题。
问题原因
这个异常通常是由于 HTML 解析器在解析包含特定格式错误的 HTML 内容时,计算出错误的数组长度 导致的。
- HTML 内容中包含过大的数字或特殊字符(如表格
colspan、rowspan、width等属性值异常) - 解析器在计算数组大小时得到负数(如
new int[-1]) - HTML 标签嵌套不正确 或 属性值格式异常
解决方案
验证并清理 HTML 内容
public class SafeHtmlEditorPane extends JEditorPane {
public void setSafeHtml(String html) {
try {
// 清理可能导致问题的属性值
String cleanedHtml = cleanProblematicAttributes(html);
this.setContentType("text/html");
this.setText(cleanedHtml);
} catch (NegativeArraySizeException e) {
System.err.println("HTML解析错误,使用备用显示方式");
this.setText("内容格式错误,无法正确显示");
}
}
private String cleanProblematicAttributes(String html) {
// 替换异常的colspan/rowspan值
html = html.replaceAll("colspan=\"(\\d+)\"", match -> {
String numStr = match.replaceAll("[^0-9]", "");
int num = Integer.parseInt(numStr);
if (num < 1 || num > 100) {
return "colspan=\"1\""; // 替换为安全值
}
return match;
});
// 清除超大width/height值
html = html.replaceAll("width=\"(\\d+)\"", match -> {
String numStr = match.replaceAll("[^0-9]", "");
int num = Integer.parseInt(numStr);
if (num < 0 || num > 10000) {
return "width=\"100\""; // 默认安全值
}
return match;
});
return html;
}
}
使用自定义 HTMLEditorKit
public class SafeHTMLEditorKit extends HTMLEditorKit {
@Override
public Document createDefaultDocument() {
HTMLDocument doc = (HTMLDocument) super.createDefaultDocument();
doc.setAsynchronousLoadPriority(-1); // 同步加载
return doc;
}
}
// 使用方式
JEditorPane editorPane = new JEditorPane();
editorPane.setEditorKit(new SafeHTMLEditorKit());
异常捕获处理
public void loadHtmlContent(JEditorPane editorPane, String htmlContent) {
try {
// 设置HTML内容
editorPane.setContentType("text/html");
// 分步设置以减少解析压力
SwingUtilities.invokeLater(() -> {
try {
editorPane.setText(htmlContent);
} catch (NegativeArraySizeException e) {
handleParsingError(editorPane, e);
}
});
} catch (Exception e) {
handleParsingError(editorPane, e);
}
}
private void handleParsingError(JEditorPane pane, Exception e) {
System.err.println("HTML解析异常:");
e.printStackTrace();
// 显示纯文本版本
pane.setContentType("text/plain");
pane.setText("【HTML解析错误】内容无法正常显示");
// 或者显示错误信息
pane.setText("Error: " + e.getMessage());
}
使用第三方库进行预处理
import org.jsoup.Jsoup;
import org.jsoup.safety.Whitelist;
public String sanitizeHtml(String dirtyHtml) {
// 使用 Jsoup 清理和标准化 HTML
org.jsoup.nodes.Document doc = Jsoup.parse(dirtyHtml);
// 修复常见问题
doc.outputSettings().prettyPrint(false);
// 获取清理后的HTML
String cleanHtml = doc.body().html();
// 移除可能导致问题的属性
cleanHtml = cleanHtml.replaceAll("colspan=\"-?\\d+\"", "colspan=\"1\"");
cleanHtml = cleanHtml.replaceAll("rowspan=\"-?\\d+\"", "rowspan=\"1\"");
return cleanHtml;
}
完整的解决示例
import javax.swing.*;
import javax.swing.text.html.*;
import java.awt.*;
public class SafeHtmlViewer extends JFrame {
private JEditorPane editorPane;
public SafeHtmlViewer() {
editorPane = new JEditorPane();
editorPane.setEditable(false);
// 使用安全的 EditorKit
editorPane.setEditorKit(createSafeHtmlKit());
JScrollPane scrollPane = new JScrollPane(editorPane);
add(scrollPane, BorderLayout.CENTER);
setSize(600, 400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
private HTMLEditorKit createSafeHtmlKit() {
return new HTMLEditorKit() {
@Override
public Document createDefaultDocument() {
HTMLDocument doc = (HTMLDocument) super.createDefaultDocument();
// 设置解析器属性
doc.setParser(new HTMLDocument.HTMLReader.Parser() {
@Override
public void parse(String in) {
try {
super.parse(in);
} catch (NegativeArraySizeException e) {
System.err.println("解析器捕获负数组大小异常,尝试继续处理");
}
}
});
return doc;
}
};
}
public void displayHtml(String html) {
try {
// 预处理 HTML
String safeHtml = preprocessHtml(html);
editorPane.setText(safeHtml);
} catch (Exception e) {
// 最后保底方案
editorPane.setText("内容显示异常");
System.err.println("HTML显示失败: " + e.getMessage());
}
}
private String preprocessHtml(String html) {
if (html == null || html.isEmpty()) {
return "<html><body></body></html>";
}
// 确保有基本结构
if (!html.toLowerCase().startsWith("<html")) {
html = "<html><body>" + html + "</body></html>";
}
return html;
}
}
推荐的最佳实践
- 使用 Jsoup 库 预处理 HTML 内容
- 捕获异常并优雅降级,而不是让程序崩溃
- 限制输入内容的大小,避免超大 HTML 文件
- 在 EDT 线程中操作 UI 组件
- 测试各种异常 HTML 格式 提前发现问题
这个问题的根本原因是 JDK 内置的 HTML 解析器对某些格式错误的处理不够健壮,所以最好的策略是 在传给 JEditorPane 之前就清理和验证 HTML 内容。
版权声明:足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播