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

Java System.out.print在打印到控制台时会消耗太多内存。有可能减少吗?,java,string,int,Java,String,Int,我有一个简单的程序: public class Test { public static void main(String[] args) { for (int i = 0; i < 1_000_000; i++) { System.out.print(1); } } } 有没有办法在控制台中打印int值而不降低内存 在本地机器上,如果(I%10000==0)System.gc(),我尝试添加循环,内存消耗平衡。但检

我有一个简单的程序:

public class Test {
    public static void main(String[] args) {
        for (int i = 0; i < 1_000_000; i++) {
            System.out.print(1);
        }
    }
}
有没有办法在控制台中打印int值而不降低内存


在本地机器上,如果(I%10000==0)System.gc(),我尝试添加
循环,内存消耗平衡。但检查解决方案的系统不会做出决定。我试图更改步骤的值,但仍然无法通过内存(应小于20mb)或时间(您需要将
int
转换为字符,而每次都不生成新的
字符串。这可以通过以下两种方式完成:

  • 编写一个自定义的“int-to-characters”方法,将
    字节[]
    转换为ASCII字节(请参阅@AndyTurner的示例代码)。然后编写
    字节[]
    ,然后重复

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

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

请注意,
System.out
是一个
PrintStream
包装
BufferedOutputStream
文件输出流
。并且,当您直接或间接使用
print
方法之一输出
字符串时,实际上是通过内部的
BufferedWriter
完成的de>PrintStream
。它很复杂……显然,
print(String)
方法会在这种复杂的地方生成垃圾


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

关于编辑2:当您从
字节[]
重复写入时,垃圾生成几乎消失。这证实了我的建议中至少有一条是可行的


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

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

java -Xms512m -Xmx512m myProgram

还有其他方法。这里有一个链接,您可以从中了解更多信息:。还有其他参数可以控制堆栈大小和其他一些内容。如果编写代码时不考虑内存使用情况,代码本身也可能会影响内存使用情况,但在您的情况下,代码太琐碎,无法执行任何操作。大多数内存问题都是在by配置jvm内存使用参数

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

分配一个字节数组,其ASCII表示形式的长度为
整数.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] = '-';

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

String str=String.valueOf(i);for(…){System.out.print(str);}
。没有帮助。即使我只打印
System.out.print()
。在峰值为~40MB的山形图上也是如此。如果你什么也不打印,仍然可以达到40MB,那么你真的没有什么其他办法了。你不能打印的比这少。这是一个真正的任务)面试的示例任务。因此,解决方案应该是。给定一个32位整数的非降序有序数组。要求从中删除所有重复。希望获得不完全在存储器中读取输入文件的解决方案,即,在该过程中仅使用恒定量的存储器。输入格式输入文件的第一行包含一个数字n,n≤ 1000000以下n行包含数字-数组的元素,每行一个。数字按非递减排序。输出格式输出文件必须按升序包含以下输入数组的唯一元素。代码中的整数用作计数器,从不打印。代码不断打印相同的字符串,因此不会产生任何垃圾。非常想念主要答案代码正在调用
print(1)
,并且每次调用时都将
1
转换为新的
字符串。它既不知道也不关心它是否在重复转换同一个数字。我不明白这有什么误导性;对于(inti=0;i<1_000_0000;i++){System.out.print(str);},在这段代码中没有整数的打印,问题仍然存在。解决方案是将jvm内存使用参数(参见我的答案)设置为引用我的答案:“可能还有其他垃圾源”。您似乎在暗示,如果不生成垃圾,就无法在Java中输出。你对此有何证据?无论如何,我建议尽量减少产生的垃圾,其中一个建议是使用固定的
字节[]
。。。而你的编辑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);
        }
    }
}
java -Xms512m -Xmx512m myProgram
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);