为了账号安全,请及时绑定邮箱和手机立即绑定

打印到控制台时 System.out.print 消耗太多内存。有没有可能减少?

打印到控制台时 System.out.print 消耗太多内存。有没有可能减少?

MM们 2022-05-21 16:48:01
我有简单的程序:public class Test {    public static void main(String[] args) {        for (int i = 0; i < 1_000_000; i++) {            System.out.print(1);        }    }}并启动剖析。结果如下:我假设内存增长是因为这个方法调用:public void print(int i) {        write(String.valueOf(i));    }有没有办法在没有内存消耗的情况下在控制台中打印int值?在本地机器上,我尝试增加if (i % 10000 == 0) System.gc();循环和内存消耗。但是检查解决方案的系统不会做出决定。我试图更改步骤的值,但仍然没有通过内存(应该工作小于 20mb)或时间(<1sec)
查看完整描述

3 回答

?
郎朗坤

TA贡献1921条经验 获得超9个赞

您需要将其转换为字符,而无需每次都int生成一个新字符。String这可以通过以下几种方式完成:

  • 编写一个自定义的“int to characters”方法,在 a 中转换为 ASCII 字节byte[](参见@AndyTurner 的示例代码)。然后写byte[]. 并重复。

  • 使用,使用自定义的“int to characters”转换器方法直接填充它,并在缓冲区已满时ByteBuffer使用 a输出字节。Channel并重复。

如果操作正确,您应该能够在不产生任何垃圾的情况下输出数字……除了一次性缓冲区。

请注意,这System.out是一个PrintStream包装 aBufferedOutputStream包装 a FileOuputStream。而且,当您String使用其中一种方法直接或间接输出 a 时print,实际上是BufferedWriter通过PrintStream. 它很复杂……显然,该print(String)方法在这种复杂性的某个地方产生了垃圾。


关于您的编辑 1:当您反复打印出一个常量字符串时,您显然仍在产生垃圾。我对此感到惊讶,但我猜它正在发生在BufferedWriter.

关于您的编辑 2:当您反复从 a 写入时byte[],垃圾生成几乎消失了。这证实了我的至少一项建议会奏效。

但是,由于您正在使用外部配置文件监视 JVM,因此您的 JVM 也在运行一个代理,该代理会定期向您的分析器发送更新。该代理很可能会产生少量垃圾。JVM 中可能还有其他垃圾来源;例如,如果您启用了 JVM GC 日志记录。


查看完整回答
反对 回复 2022-05-21
?
宝慕林4294392

TA贡献2021条经验 获得超8个赞

由于您发现打印 abyte[]将内存分配保持在所需范围内,因此您可以使用以下事实:


分配一个字节数组,其 ASCII 表示的长度为Integer.MIN_VALUE(11 - int 可以是最长的)。然后您可以向后填充数组以转换数字i:


int p = buffer.length;

if (i == Integer.MIN_VALUE) {

  buffer[--p] = (byte) ('0' - i % 10);

  i /= 10;

}

boolean neg = i < 0;

if (neg) i = -i;

do {

  buffer[--p] = (byte) ('0' + i % 10);

  i /= 10;

} while (i != 0);

if (neg) buffer[--p] = '-';

然后将其写入您的流:


out.write(buffer, p, buffer.length - p);

您可以重复使用相同的缓冲区来写入任意数量的数字。


查看完整回答
反对 回复 2022-05-21
?
慕田峪4524236

TA贡献1875条经验 获得超5个赞

内存使用模式对于 java 来说是典型的。您的代码无关紧要。要控制 java 内存使用,您需要使用一些 -X 参数,例如“-Xms512m -Xmx512m”将最小和最大堆大小设置为 512m。顺便说一句,为了最小化类似母猪的内存图,建议将最小和最大大小设置为相同的值。当您运行 java 时,可以在命令行上将这些参数提供给 java,例如:

java -Xms512m -Xmx512m myProgram

还有其他方法。这是一个链接,您可以在其中阅读更多信息:Oracle 文档。还有其他参数控制堆栈大小和其他一些东西。如果在没有考虑内存使用情况的情况下编写代码本身,也可能会影响内存使用,但在您的情况下,它的代码太琐碎而无法做任何事情。大多数内存问题都是通过配置 jvm 内存使用参数来解决的


查看完整回答
反对 回复 2022-05-21
  • 3 回答
  • 0 关注
  • 663 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号