使用限制

原文: https://docs.oracle.com/javase/tutorial/jaxp/limits/using.html

环境评估

评估包括在系统级别,可用于应用程序的内存量,是否接受和处理来自不受信任来源的 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的特殊属性。以下代码段显示了使用该属性的示例:

  1. 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 属性相同的方式设置限制。它们可以通过工厂方法或通过解析器设置:

  1. DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
  2. dbf.setAttribute(name, value);
  3. SAXParserFactory spf = SAXParserFactory.newInstance();
  4. SAXParser parser = spf.newSAXParser();
  5. parser.setProperty(name, value);
  6. XMLInputFactory xif = XMLInputFactory.newInstance();
  7. xif.setProperty(name, value);
  8. SchemaFactory schemaFactory = SchemaFactory.newInstance(schemaLanguage);
  9. schemaFactory.setProperty(name, value);
  10. TransformerFactory factory = TransformerFactory.newInstance();
  11. factory.setAttribute(name, value);

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

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

使用系统属性

如果更改代码不可行,则系统属性可能很有用。

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

  1. public static final String SP_GENERAL_ENTITY_SIZE_LIMIT = "jdk.xml.maxGeneralEntitySizeLimit";
  2. //set limits using system property
  3. System.setProperty(SP_GENERAL_ENTITY_SIZE_LIMIT, "2000");
  4. //this setting will affect all processing after it's set
  5. ...
  6. //after it is done, clear the property
  7. 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文件来设置限制:

  1. jdk.xml.maxGeneralEntitySizeLimit=2000

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

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