使用限制
原文: https://docs.oracle.com/javase/tutorial/jaxp/limits/using.html
环境评估
评估包括在系统级别,可用于应用程序的内存量,是否接受和处理来自不受信任来源的 XML,XSD 或 XSL 源,以及在应用程序级别,是否使用某些构造(如 DTD)。
记忆设定和限制
XML 处理可能非常耗费内存。应允许使用的内存量取决于特定环境中应用程序的要求。必须防止处理格式错误的 XML 数据消耗过多的内存。
默认限制通常设置为允许大多数应用程序的合法 XML 输入,并允许小型硬件系统(如 PC)使用内存。建议将限制设置为可能的最小值,以便在消耗大量内存之前捕获任何格式错误的输入。
限制是相关的,但并非完全多余。您应该为所有限制设置适当的值:通常应将限制设置为比默认值小得多的值。
例如,可以设置ENTITY_EXPANSION_LIMIT
和GENERAL_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 运行时,它会打印出下表:
属性 | 限制 | 总大小 | 尺寸 | 实体名称 |
---|---|---|---|---|
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 |
5000 | 55425 | 0 | null |
GENERAL_ENTITY_SIZE_LIMIT |
0 | 0 | 0 | null |
PARAMETER_ENTITY_SIZE_LIMIT |
百万 | 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";
//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);
请注意,属性的值应为整数。如果输入的值不包含可解析的整数,则抛出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
。预期属性的值为整数。如果输入的值不包含可解析的整数,则抛出NumberFormatException
;见方法 parseInt(String)
。
在文件中设置属性后,JDK 和 JRE 的所有调用都将遵循限制。