优先使用StAX流式解析大型XML以避免内存溢出,其拉模式控制灵活、内存占用低;次选SAX推模式适用于校验统计;禁用DOM以防OOM,必要时结合预扫描与流式转换。

Java解析大型XML文件,关键不是用DOM加载整个文档,而是用流式处理避免内存溢出。SAX和StAX是主流选择,其中StAX更易用、更灵活,适合大多数场景。
优先使用StAX(Streaming API for XML)
StAX是拉模式(pull-based)解析器,程序主动从XML流中读取事件,控制权在开发者手上,内存占用低且代码可读性好。
- 用XMLInputFactory创建解析器,调用createXMLEventReader获取事件流
- 逐个读取START_ELEMENT、CHARACTERS、END_ELEMENT等事件,只处理关心的节点
- 遇到大文本内容(如CDATA或长字段),用hasText()和getText()按需提取,避免缓存整段字符串
- 示例:只提取所有
下的和,跳过其余结构,不构建对象树
谨慎使用SAX(Simple API for XML)
SAX是推模式(push-based),通过回调处理事件,性能高但逻辑易分散,适合纯校验或统计类任务。
- 实现DefaultHandler,重写startElement、characters、endElement
- 用栈或状态变量跟踪当前路径(如
inItem && inTitle),避免深度嵌套时误匹配 - 注意characters()可能被多次调用(因缓冲分片),需累积字符再处理
- 不适合需要随机访问或回溯的场景,比如跨节点关联数据
避免DOM,除非文件确定很小
DOM会把整个XML加载为内存中的树结构,10MB XML可能占用50MB+堆空间,极易触发GC甚至OOM。
立即学习“Java免费学习笔记(深入)”;
- 即使用DocumentBuilder.setEntityResolver禁用外部实体,也无法解决内存膨胀问题
- 若必须用DOM(如需XPath查询或多次遍历),先用StAX预扫描,确认文件大小或节点数量是否可控
- 考虑搭配javax.xml.transform.Transformer做流式转换,把大XML切分为小片段再分别DOM解析
实用技巧与注意事项
真实业务中,常需结合数据结构与性能做取舍。










