我有一个 java 应用程序,它从 Oracle 11g 数据库版本 11.2.0.4.0(使用 spring 4)中提取大型 xml 并将它们存储在文件中。我们在提取包含多字节字符的数据时遇到问题。根据多字节在 xml 中的位置,有时会将多字节分成两部分。看来问题出在jdbc的版本和安装的oracle客户端上。因此,我们迁移到 Oracle 客户端 18 和 ojdb8.jar,保持代码不变。多字节问题已经解决,但现在我们遇到了以前没有发生过的内存问题。我得到的错误是:
内存不足,Java 运行时环境无法继续。
native 内存分配 (mmap) 无法映射 256376832 字节以提交保留内存。
我尝试过使用 java 命令参数,但没有效果。这就是我正在运行的: java -Dfile.encoding=UTF8 -Doracle.jdbc.timezoneAsRegion=false -Xmx10240m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp -XX:NativeMemoryTracking=detail -XX:+StartAttachListener -XX:+UnlockDiagnosticVMOptions -XX:+PrintNMTStatistics
将 Xmx 减少到 512m 最终会耗尽堆内存。
我使用 jcmd VM.native_memory benchmark/summary.diff 和 GC.class_stats 监视应用程序的内存,最大的内存消耗者之一是 String 对象。我无法理解其余的内容。
sql 是: 选择 XML_DATA 从表中....
xml_data 列定义为: XML_DATA NOT NULL SYS.XMLTYPE 存储二进制
在 java 中将其映射到 oracle.xdb.XMLType:
public List<XMLType> extractXmlDataList(String sqlExtractionQuery, Key key) {
MapSqlParameterSource namedSqlParams = createKeyParamMap(key);
List<XMLType> dataList = namedParameterJdbcTemplate.queryForList(sqlExtractionQuery, namedSqlParams, XMLType.class);
return dataList;
}
protected void extractXmlData(Key key) {
List<XMLType> xmlRecs = producerDao.extractXmlDataList(sqlExtractionQuery, patentKey);
if (xmlRecs != null && xmlRecs.size() > 0) {
for (XMLType xmlData : xmlRecs) {
String xmlText = xmlData.getStringVal();
//create nu.xom.Document
Builder parser = new Builder();
Document xmlDocument = parser.build(xmlText, null);
}
}
}
迁移到 Oracle 客户端 18 和 jdbc8.jar 为何对内存消耗影响如此之大?
最佳答案
内存问题已通过使用 xmlserialize 而不是 Oracle Java XMLType 对象得到解决。仍然使用Oracle客户端18和ojdbc8.jar。多字节 UTF8 分割不再有问题。
关于java - 使用 jdbc8.jar 和 Oracle 客户端 18 时 native 内存分配 (mmap) 无法映射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56257884/