# 使用限制

> 原文： [https://docs.oracle.com/javase/tutorial/jaxp/limits/using.html](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](sample.html) 。

当程序在 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)`](https://docs.oracle.com/javase/8/docs/api/java/lang/Integer.html#parseInt-java.lang.String-) 。

有关下载示例代码的更多信息，请参见 [Samples](sample.html) 。

## 使用 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)`](https://docs.oracle.com/javase/8/docs/api/java/lang/Integer.html#parseInt-java.lang.String-) 。

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