Java中的流如何影响内存消耗?

时间:2013-08-04 13:18:44

标签: java memory

我多次使用过流,但我从来没有读过很多关于它们实际工作情况的信息。除了流只是一个比喻之外,我也不太了解它们。流只表示字节序列。我不太了解它们实际上是如何工作的,我想在Java中打开一个文件流与具有向流提供“指针”功能的操作系统进行交互。

基本上我的问题是流如何影响内存消耗。例如,当你有一个输入流并开始从它读取时,你只开始增加读取的字节数的内存消耗?在Java中打开流时,在开始阅读之前,实际上并没有加载完整的文件?如果从一个流中读取并直接写入另一个流,则只增加内存的读取字节数(可能还有缓冲区)?如果你在java中读取字节数组的字节,那么你会增加文件大小的内存消耗?

可能听起来像一个奇怪的问题,但我可能需要一些指导/纠正我的理解。感谢。

2 个答案:

答案 0 :(得分:5)

上面的所有答案都是很好的答案,但我不相信他们会回答你关于记忆消耗的原始问题。

在Java中,您可以通过多种方式查看流。首先,您拥有Raw流,它是最低级别的流,并以最小的内存开销与底层操作系统(文件,网络等)交互。其次是缓冲流,可用于包装原始流并添加一些缓冲并显着提高性能。流缓冲为缓冲添加了固定数量的内存开销,可以由您的应用程序设置。不确定默认值是什么,但它可能是最小的,如32K。

第三种类型的流是一个内存流(即ByteArrayInput / Ouput),它们使用尽可能多的内存,并且会根据需要增长,并且在引用计数变为零之前不会丢弃它们的内存(它们不是使用时间更长)。这些流非常有用,但显然会占用大量内存。

最终类型实际上不是流,而是一类称为读者的I / O,它提供了与流之间的数据转换的协助,如上所述。这些流可以在raw上运行。缓冲或内存流,将消耗与正在使用的基础流一样多的内存。

答案 1 :(得分:3)

InputStream开始阅读后,几乎没有“强大的内存开销”。用于打开文件的操作系统开销非常小,而在JVM中用于新对象分配的开销很小。如果使用BufferedInputStream,默认情况下为8KB,也可能会产生很小的开销。

写作的开销很大程度上取决于你写的位置。如果它是FileOutputStream,则它与上述相同。如果它是ByteArrayOutputStream,那么在最好的情况下它是(2 *流长度)字节,在最坏的情况下是(3 *流长度)字节。即将InputStream中的10k字节复制到字节数组中,在最坏的情况下将分配30k字节。

原因是ByteArrayOutputStream大小在达到限制后增长了2倍,并且在您调用toByteArray()时也会分配新的缓冲区。