使用限制

Environment Evaluation

评估包括在系统级别上可用于应用程序的内存量,是否接受和处理来自不受信任来源的 XML,XSD 或 XSL 源,以及在应用程序级别上,是否使用某些构造(如 DTD)。

内存设置和限制

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

通常将默认限制设置为允许大多数应用程序使用合法的 XMLImporting,而小型硬件系统(例如 PC)则允许使用内存。建议将限制设置为最小的可能值,以使任何格式错误的 Importing 都可以在占用大量内存之前被catch。

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

例如,可以设置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");

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

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

PropertyLimitTotal SizeSizeEntity Name
ENTITY_EXPANSION_LIMIT6400014170null
MAX_OCCUR_NODE_LIMIT500000null
ELEMENT_ATTRIBUTE_LIMIT1000000null
TOTAL_ENTITY_SIZE_LIMIT50000000554250null
GENERAL_ENTITY_SIZE_LIMIT000null
PARAMETER_ENTITY_SIZE_LIMIT100000007303%MultiScriptExpression
MAX_ELEMENT_DEPTH_LIMIT020null
MAX_NAME_LIMIT10001313null
ENTITY_REPLACEMENT_LIMIT300000000null

在此示例中,实体引用或实体扩展的总数为 1417;默认限制为 64000.所有实体的总大小为 55425;解析所有引用后,最大参数实体为%MultiScriptExpression,Long 度为 7303;默认限制为 50000000.默认限制为 1000000.

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

Setting Limits

可以与其他 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";

//set limits using system property
System.setProperty(SP_GENERAL_ENTITY_SIZE_LIMIT, "2000");

//this setting will affect all processing after it's set
...

//after it is done, clear the property
System.clearProperty(SP_GENERAL_ENTITY_SIZE_LIMIT);

请注意,属性的值应为整数。如果 Importing 的值不包含可分析的整数,则将引发NumberFormatException;参见方法parseInt(String)

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

使用 jaxp.properties 文件

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

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

jdk.xml.maxGeneralEntitySizeLimit=2000

请注意,属性名称与系统属性的名称相同,并且前缀为jdk\.xml。这些属性的值应为整数。如果 Importing 的值不包含可分析的整数,则将抛出NumberFormatException;否则,将抛出NumberFormatException。参见方法parseInt(String)

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