加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

Scala – 在本地范围内的大量文件上执行XML.loadFile时的高堆使

发布时间:2020-12-16 18:32:24 所属栏目:安全 来源:网络整理
导读:我试图从大量的xmls创建一个对象树.但是,当我在大约2000 xml文件(范围从100KB到200MB)上运行以下代码时(注意我已经注释掉了创建对象树的代码),我获得了8-9GB的大内存占用.我希望在下面的示例中内存占用量最小,因为代码不会保留任何引用,它只会创建Elem并将其
我试图从大量的xmls创建一个对象树.但是,当我在大约2000 xml文件(范围从100KB到200MB)上运行以下代码时(注意我已经注释掉了创建对象树的代码),我获得了8-9GB的大内存占用.我希望在下面的示例中内存占用量最小,因为代码不会保留任何引用,它只会创建Elem并将其抛弃.运行完整GC后,堆内存保持不变.

def addDir(dir: File) {
dir.listFiles.filter(file => file.getName.endsWith("xml.gz")).foreach { gzipFile =>
    addGzipFile(gzipFile)
}
}
def addGzipFile(gzipFile: File) {
val is = new BufferedInputStream(new GZIPInputStream(new FileInputStream(gzipFile)))
val xml = XML.load(is)
// parse xml and create object tree
is.close()
}

我的JVM选项是:-server -d64 -Xmx16G -Xss16M -XX:DoEscapeAnalysis -XX:UseCompressedOops

而jmap -histo的输出看起来像这样

num     #instances         #bytes  class name
----------------------------------------------
   1:      67501390     1620033360  scala.collection.immutable.$colon$colon
   2:      37249187     1254400536  [C
   3:      37287806     1193209792  java.lang.String
   4:      37200976      595215616  scala.xml.Text
   5:      18600485      595215520  scala.xml.Elem
   6:       3420921       82102104  scala.Tuple2
   7:        213938       58213240  [I
   8:       1140334       36490688  scala.collection.mutable.ListBuffer
   9:       2280468       36487488  scala.runtime.ObjectRef
  10:       1140213       36486816  scala.collection.Iterator$$anon$24
  11:       1140210       36486720  scala.xml.parsing.FactoryAdapter$$anonfun$startElement$1
  12:       1140210       27365040  scala.collection.immutable.Range$$anon$2
...
Total     213412869     5693850736

解决方法

我无法重现这种行为.我使用以下程序:

import java.io._
import xml.XML

object XMLLoadHeap {

  val filename = "test.xml"

  def addFile() {
    val is = new BufferedInputStream(new FileInputStream(filename))
    val xml = XML.load(is)
    is.close()
    println(xml.label)
  }

  def createXMLFile() {
    val out = new FileWriter(filename)
    out.write("<foo>n")
    (1 to 100000) foreach (i => out.write("  <bar baz="boom"/>n"))
    out.write("</foo>n")
    out.close()
  }

  def main(args:Array[String]) {
    println("XMLLoadHeap")
    createXMLFile()
    (1 to args(0).toInt) foreach { i => 
      println("processing " + i)
      addFile()
    }
  }

}

我使用以下选项运行它:-Xmx128m -XX:HeapDumpOnOutOfMemoryError -verbose:gc,它基本上看起来可以无限期运行.

您可以尝试在仅使用最大的XML文件时查看是否执行此操作.问题可能不是处理许多文件,而是处理最大的文件.当在64位计算机上使用虚拟200MB XML文件进行测试时,我发现需要大约3G内存.如果是这种情况,您可能需要使用拉解析器.见XMLEventReader.

除此之外,假设您没有创建对象树,您可以使用-Xmx4G -XX:HeapDumpOnOutOfMemoryError,然后使用像MAT这样的工具分析堆转储.4GB应该足以解析最大的XML文件,到时候你得到内存不足错误,可能会分配足够的对象来确定哪个对象阻止了GC.很可能是一个持有各种解析的XML对象的对象.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读