文档

Java™ 教程
隐藏目录
使用限制
路径:Java XML处理API(JAXP)
课程:处理限制

使用限制

环境评估

评估包括系统级别的应用程序可用内存量,是否接受和处理来自不受信任的源的XML、XSD或XSL源,以及应用程序级别的是否使用了DTD等构造。

内存设置和限制

XML处理可能需要非常多的内存。应该允许消耗的内存量取决于特定环境中应用程序的需求。必须防止处理格式错误的XML数据时消耗过多的内存。

默认限制通常设置为允许大多数应用程序的合法XML输入,并允许在小型硬件系统(如PC)上使用内存。建议将限制设置为最小可能值,以便在消耗大量内存之前捕获任何格式错误的输入。

这些限制是相关的,但并非完全冗余。您应该为所有限制设置适当的值:通常,限制应设置为比默认值小得多的值。

例如,可以设置ENTITY_EXPANSION_LIMITGENERAL_ENTITY_SIZE_LIMIT来防止过多的实体引用。但是,如果不知道扩展和实体大小的确切组合,TOTAL_ENTITY_SIZE_LIMIT可以作为总体控制。同样,TOTAL_ENTITY_SIZE_LIMIT控制替换文本的总大小,如果文本是一个非常大的XML块,ENTITY_REPLACEMENT_LIMIT设置对文本中可以出现的节点总数的限制,以防止过载系统。

使用getEntityCountInfo属性估算限制

为了帮助您分析应为限制设置什么值,有一个特殊的属性叫做http://www.oracle.com/xml/jaxp/properties/getEntityCountInfo可用。以下代码片段显示了使用该属性的示例:

parser.setProperty("http://www.oracle.com/xml/jaxp/properties/getEntityCountInfo", "yes");

有关下载示例代码的更多信息,请参阅示例

当使用W3C MathML 3.0中的DTD运行程序时,它会打印出以下表格:

属性 限制 总大小 大小 实体名称
ENTITY_EXPANSION_LIMIT 64000 1417 0 null
MAX_OCCUR_NODE_LIMIT 5000 0 0 null
ELEMENT_ATTRIBUTE_LIMIT 10000 0 0 null
TOTAL_ENTITY_SIZE_LIMIT 50000000 55425 0 null
GENERAL_ENTITY_SIZE_LIMIT 0 0 0 null
PARAMETER_ENTITY_SIZE_LIMIT 1000000 0 7303 %MultiScriptExpression
MAX_ELEMENT_DEPTH_LIMIT 0 2 0 null
MAX_NAME_LIMIT 1000 13 13 null
ENTITY_REPLACEMENT_LIMIT 3000000 0 0 null

在这个例子中,实体引用的总数,或实体扩展,为1417;默认限制为64000。所有实体的总大小为55425;默认限制为50000000。最大的参数实体是%MultiScriptExpression,在解析所有引用后长度为7303;默认限制为1000000。

如果这是应用程序预期处理的最大文件,建议将限制设置为较小的数字。例如,ENTITY_EXPANSION_LIMIT为2000,TOTAL_ENTITY_SIZE_LIMIT为100000,PARAMETER_ENTITY_SIZE_LIMIT为10000。

设置限制

限制可以像其他JAXP属性一样进行设置。可以通过工厂方法或解析器进行设置:

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setAttribute(name, value);
 
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser parser = spf.newSAXParser();
parser.setProperty(name, value);
 
XMLInputFactory xif = XMLInputFactory.newInstance();
xif.setProperty(name, value);
 
SchemaFactory schemaFactory = SchemaFactory.newInstance(schemaLanguage);
schemaFactory.setProperty(name, value);
 
TransformerFactory factory = TransformerFactory.newInstance();
factory.setAttribute(name, value);

以下示例演示如何使用DocumentBuilderFactory设置限制:

dbf.setAttribute(JDK_ENTITY_EXPANSION_LIMIT, "2000");
dbf.setAttribute(TOTAL_ENTITY_SIZE_LIMIT, "100000");
dbf.setAttribute(PARAMETER_ENTITY_SIZE_LIMIT, "10000"); 
dbf.setAttribute(JDK_MAX_ELEMENT_DEPTH, "100"); 

使用系统属性

如果无法更改代码,系统属性可能很有用。

要为整个JDK或JRE的调用设置限制,请在命令行上设置系统属性。要仅为应用程序的一部分设置限制,可以在该部分之前设置系统属性,并在之后清除。以下代码显示了如何使用系统属性:

public static final String SP_GENERAL_ENTITY_SIZE_LIMIT = "jdk.xml.maxGeneralEntitySizeLimit";

//使用系统属性设置限制
System.setProperty(SP_GENERAL_ENTITY_SIZE_LIMIT, "2000");

//此设置将影响设置之后的所有处理
...

//完成后,清除属性
System.clearProperty(SP_GENERAL_ENTITY_SIZE_LIMIT);

请注意,属性的值应为整数。如果输入的值不包含可解析的整数,则会抛出NumberFormatException;请参阅方法parseInt(String)

有关下载示例代码的更多信息,请参阅示例

使用jaxp.properties文件

jaxp.properties文件是一个配置文件。它通常位于${java.home}/lib/jaxp.properties,其中java.home是JRE的安装目录,例如,[安装目录的路径]/jdk8/jre。

可以通过将以下行添加到jaxp.properties文件中来设置限制:

jdk.xml.maxGeneralEntitySizeLimit=2000

请注意,属性名称与系统属性的名称相同,并具有前缀jdk.xml。属性的值应为整数。如果输入的值不包含可解析的整数,则会抛出NumberFormatException;请参阅方法parseInt(String)

当在文件中设置属性时,所有JDK和JRE的调用都将遵守该限制。


上一页:作用域和顺序
下一页:错误处理