代码之家  ›  专栏  ›  技术社区  ›  ip696

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

  •  0
  • ip696  · 技术社区  · 6 年前

    我有一个简单的程序:

    public class Test {
        public static void main(String[] args) {
            for (int i = 0; i < 1_000_000; i++) {
                System.out.print(1);
            }
        }
    }
    

    enter image description here

    我假设内存增长是因为这个方法调用:

    public void print(int i) {
            write(String.valueOf(i));
        }
    

    有办法打印吗 整数 控制台中没有内存缩减的值?

    在本地计算机上,我尝试添加 if (i % 10000 == 0) System.gc(); 使循环和内存消耗均衡。但检查解决方案的系统不会做出决定。我试图更改步骤的值,但仍然没有在内存中(应小于20mb)或在时间上(1秒)传递

        String str = "hz";
        for (int i = 0; i < 1_000_0000; i++) {
            System.out.print(str);
        } 
    

    enter image description here 但同样的结果:

    编辑2 如果我写这段代码

    public class Test {
        public static void main(String[] args) {
            byte[] bytes = "hz".getBytes();
            for (int i = 0; i < 1_000_0000; i++) {
                System.out.write(bytes, 0, bytes.length);
            }
        }
    }
    

    enter image description here

    因此,我不认为Java在制造噪音。在这两种情况下都是这样。

    3 回复  |  直到 6 年前
        1
  •  1
  •   Stephen C    6 年前

    你需要转换 int 不生成新字符 String 每次你这样做。这可以通过以下几种方式实现:

    • 编写一个自定义的“int to characters”方法,该方法在 byte[] (参见@AndyTurner的示例代码)。然后写下 字节[]

    • 使用 ByteBuffer ,使用自定义的“int to characters”转换方法直接填充,并使用 Channel

    如果正确的话,你应该能够输出数字而不产生任何垃圾。。。除了你的一次性缓冲。

    System.out 是一个 PrintStream 包装 BufferedOutputStream FileOuputStream . 当你输出一个 字符串 print 方法,实际上是通过 BufferedWriter 它是 . 很复杂。。。很明显 print(String) 方法在这种复杂性的某个地方生成垃圾。


    缓冲写入程序 .

    关于你的编辑2:当你从 字节[]

    但是,由于您使用外部概要文件监视JVM,因此JVM还运行 它定期向您的探查器发送更新。该代理很可能会生成少量垃圾。JVM中可能还有其他垃圾源;例如,如果启用了JVM GC日志记录。

        2
  •  0
  •   Andy Turner    6 年前

    byte[] 将内存分配保持在所需的范围内,可以使用以下事实:

    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);
    

    你可以重复使用同一个缓冲区来写尽可能多的数字。

        3
  •  -3
  •   Michael Gantman    6 年前

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

    java -Xms512m -Xmx512m myProgram
    

    还有其他方法。以下是一个链接,您可以在其中阅读更多有关它的信息: Oracle docs . 还有其他一些参数控制stacksize和其他一些东西。如果不考虑内存使用,代码本身可能也会影响内存使用,但在您的情况下,代码太琐碎,无法执行任何操作。大多数内存问题是通过配置jvm内存使用参数来解决的