Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/384.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
减少内存占用,同时使用大型XML DOM';Java中的s_Java_Memory_Xml Parsing - Fatal编程技术网

减少内存占用,同时使用大型XML DOM';Java中的s

减少内存占用,同时使用大型XML DOM';Java中的s,java,memory,xml-parsing,Java,Memory,Xml Parsing,我们的应用程序需要获取以XML格式表示的客户机数据(几个文件),并将其解析为我们的通用XML格式(带有模式的单个文件)。为此,我们使用apache的XMLBeans数据绑定框架。下面简要描述该过程的步骤 首先,我们获取指向磁盘上客户端XML文件的原始java.io.File对象,并将其加载到集合中。然后,我们迭代这个集合,为每个文件创建一个apache.xmlbeans.XmlObject。在将所有文件解析为XmlObjects之后,我们创建了4个集合,其中包含我们感兴趣的XML文档中的各个对象

我们的应用程序需要获取以XML格式表示的客户机数据(几个文件),并将其解析为我们的通用XML格式(带有模式的单个文件)。为此,我们使用apache的XMLBeans数据绑定框架。下面简要描述该过程的步骤

首先,我们获取指向磁盘上客户端XML文件的原始java.io.File对象,并将其加载到集合中。然后,我们迭代这个集合,为每个文件创建一个apache.xmlbeans.XmlObject。在将所有文件解析为XmlObjects之后,我们创建了4个集合,其中包含我们感兴趣的XML文档中的各个对象(很明显,这些不是手工制作的对象,而是我只能描述为apache的XMLBeans框架创建的“代理”对象)。最后一步,我们迭代这些集合以生成我们的XML文档(在内存中),然后将其保存到磁盘

对于大多数用例,当给定“-Xmx1500m”命令行参数时,该过程工作良好,可以轻松地在JVM中运行。然而,当客户向我们提供“大型数据集”时,就会出现问题。在本例中,较大的是分布在7个文件上的123Mb客户端XML。这样的数据集导致我们的代码集合中填充了近40000个上述“代理对象”。在这些情况下,内存的使用量非常高我没有得到任何outofmemory异常程序只是挂起,直到发生垃圾回收,释放出少量内存,然后程序继续,使用完这个新空间,循环重复。这些解析会话目前需要4-5个小时。我们的目标是在一小时内把这一数字降到最低

需要注意的是,将客户机xml转换为xml所需的计算需要所有xml数据进行交叉引用。因此,我们不能实现一个顺序解析模型,也不能将这个过程批处理成更小的块

我到目前为止所做的尝试

在每次请求数据时,加载文件、查找数据并释放对这些对象的引用,而不是将所有123Mb的客户端xml保存在内存中。这似乎确实减少了进程中消耗的内存量,但正如您可以想象的那样,恒定I/O所花费的时间减少了内存占用的好处

我怀疑一个问题是,我们持有一个XmlObject[],用于存储价值123Mb的XML文件以及从这些文档中获取的对象集合(使用xpath查询)。为了补救,我改变了逻辑,以便直接查询文档,而不是查询这些集合。这里的想法是,在任何时候都不存在4个大规模列表,其中包含10个1000个对象,而只是大量的XmlObjects集合。这似乎根本没有什么不同,在某些情况下,会进一步增加内存占用

现在抓着救命稻草,我认为在写入磁盘之前,我们用来在内存中构建我们的xml的XmlObject变得太大,无法与所有客户端数据一起维护。但是,对该对象进行一些sizeOf查询后发现,该对象的最大容量小于10Kb。在阅读了XmlBeans如何管理大型DOM对象之后,它似乎使用了某种形式的缓冲编写器,因此,它很好地管理了这个对象

所以现在我没有主意了;无法使用SAX方法代替内存密集型DOM方法,因为我们的应用程序在任何时候都需要100%的客户端数据,在我们完全需要这些数据之前,我们无法延迟请求这些数据,因为转换过程需要大量循环,磁盘I/O时间不值得节省内存空间,而且我似乎无法以这样的方式构造逻辑,以减少内部java集合占用的空间量。我在这里运气不好吗?如果我想将价值123Mb的xml数据解析为我们的xml格式,而我不能用1500m的内存分配,我必须接受这一点吗?虽然123Mb在我们的领域中是一个很大的数据集,但我无法想象其他人在同一时间从未对Gb的数据做过类似的事情

其他可能重要的信息

  • 我用JProbe试着看看它是否能告诉我什么有用的东西。虽然我是一个分析noob,但我浏览了他们关于内存泄漏和线程锁的教程,理解了它们,代码中似乎没有任何泄漏或瓶颈。在使用大数据集运行应用程序后,我们很快在内存分析屏幕上看到“锯片”类型的形状(请参见附图)随着PS Eden空间被PS Old Gen的大量绿色块所占据。这让我相信这里的问题仅仅是对象集合占用的空间量,而不是未使用内存的泄漏

  • 我在64位Windows 7平台上运行,但这需要在32位环境下运行

我将采取的方法是对文件进行两次传递,在这两种情况下都使用SAX

第一步是将计算中所需的“交叉引用”数据解析为自定义对象,并将它们存储在
Map
s中。如果“交叉引用”数据很大,那么请使用分布式缓存(如果您从
Map
s开始,一致性是最合适的)


第二步将解析文件,检索“交叉引用”数据以根据需要执行计算,然后使用
javax.XML.stream
API编写输出XML。

可能大小不重要,但您从我这里得到+1;-)。虽然不可能在2次解析中完成此处理,但已将其标记为应答,尝试这样做会让我发现内存占用过大的真正原因。与相应的XML文档相比,Apache的XMLBeans框架生成的DOM大得不成比例