使用限制
Environment Evaluation
评估包括在系统级别上可用于应用程序的内存量,是否接受和处理来自不受信任来源的 XML,XSD 或 XSL 源,以及在应用程序级别上,是否使用某些构造(如 DTD)。
内存设置和限制
XML 处理可能会占用大量内存。应允许消耗的内存量取决于特定环境中应用程序的要求。必须防止处理格式错误的 XML 数据占用过多的内存。
通常将默认限制设置为允许大多数应用程序使用合法的 XMLImporting,而小型硬件系统(例如 PC)则允许使用内存。建议将限制设置为最小的可能值,以使任何格式错误的 Importing 都可以在占用大量内存之前被catch。
限制是相关的,但并非完全多余。您应该为所有限制设置适当的值:通常,限制应设置为比默认值小得多的值。
例如,可以设置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 运行程序时,它会打印出下表:
Property | Limit | Total Size | Size | Entity Name |
---|---|---|---|---|
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;解析所有引用后,最大参数实体为%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 的所有调用都将遵守该限制。