JVM创建CSV文件并在运行时压缩所需的内存

时间:2012-12-16 14:36:49

标签: java object memory-management csv

我正在使用String缓冲区和字节数组创建两个CSV文件  我使用ZipOutputStream生成zip文件。每个csv文件将具有包含14列的20K记录。实际上,记录是从DB中提取的并存储在ArrayList中。我必须迭代列表并构建StringBuffer并将StringBuffer转换为字节数组以将其转换为zip条目。

我希望知道 JVM从存储ArrayList中的记录开始执行整个过程所需的内存。
 我在下面提供了代码段。

StringBuffer responseBuffer = new StringBuffer();
    String response = new String();
    response = "Hello, sdksad, sfksdfjk, World, Date, ask, askdl, sdkldfkl, skldkl, sdfklklgf, sdlksldklk, dfkjsk, dsfjksj, dsjfkj, sdfjkdsfj\n";
    for(int i=0;i<20000;i++){
        responseBuffer.append(response);
    }
    response = responseBuffer.toString();
    byte[] responseArray = response.getBytes();
    res.setContentType("application/zip");
    ZipOutputStream zout = new ZipOutputStream(res.getOutputStream());
    ZipEntry parentEntry = new ZipEntry("parent.csv");
    zout.putNextEntry(parentEntry);
    zout.write(responseArray);
    zout.closeEntry();
    ZipEntry childEntry = new ZipEntry("child.csv");
    zout.putNextEntry(childEntry);
    zout.write(responseArray);
    zout.closeEntry();
    zout.close();

请帮我解决这个问题。提前谢谢。

3 个答案:

答案 0 :(得分:2)

要分析内存使用情况,您可以使用 Profiler

JProfilerYourKit非常擅长这样做。

VisualVM在某种程度上也很好。

答案 1 :(得分:2)

我猜你已经尝试过计算将为StringBuffer和字节数组分配多少字节。但问题是你不能真正知道你的应用程序将使用多少内存,除非你有CSV记录大小的上限。我是如果你想要你的软件稳定,强大和可扩展,我担心你会问错误的问题:你应该努力使用固定数量的内存执行你需要做的任务,在你的情况下似乎很容易。

关键是,在您的情况下,处理完全是FIFO - 您从数据库中读取记录,然后将它们(以相同的顺序)写入FIFO流(在这种情况下为OutputStream)。甚至zip压缩也是基于流的,并且在内部使用固定数量的内存,所以你在那里完全安全。

不是在巨大的String中缓冲整个输入,而是将其转换为巨大的字节数组,然后将其写入输出流 - 您应该从数据库中分别读取每个响应元素(或者说固定大小的块,比如说100一次记录),并将其写入输出流。像

这样的东西
res.setContentType("application/zip");
ZipOutputStream zout = new ZipOutputStream(res.getOutputStream());
ZipEntry parentEntry = new ZipEntry("parent.csv");
zout.putNextEntry(parentEntry);
while (... fetch entries ...)
    zout.write(...data...)
zout.closeEntry();

这种方法的优点在于,因为它适用于小块,您可以轻松估计它们的大小,并为您的JVM分配足够的内存,使其永远不会崩溃。而且你知道,如果你的CSV文件将来变得超过20K行,它仍然可以工作。

答案 2 :(得分:0)

您可以使用MemoryTestbench来衡量记忆。

http://www.javaspecialists.eu/archive/Issue029.html

这篇文章描述了该怎么做。它很简单,并且精确到1个字节,我经常使用它 它甚至可以从junit测试用例运行,因此它非常有用,而无法运行探查器 来自junit测试案例。

使用该apporach,您甚至可以测量一个Integer对象的内存大小。

但是拉链有一件特别之处。 Zipstream使用本机c库,在这种情况下,MemoryTestbench可能无法测量该内存,只测量java部分 你应该尝试两种变体,MemroyTestbench和profilers(jprof)。