如何在无限循环中使用更少的堆空间?

伦尼

我的Java应用程序的内存使用出现问题。同时具有堆空间和非堆空间。现在,我专注于堆空间。

我的应用程序是一个SocketServer,它通过DataInputStream获取输入。我正在以字节数组形式读取信息。每秒输入的输入量是不规则的,但是我们说的是每秒400字节到1.000字节的空间,峰值可能会更高。

因为我的程序是服务器,所以它无休止地等待输入。现在,我遇到了一个问题,我的堆空间随着时间的推移而上升,所有5-10分钟的时间都增加了0.5MB。

我使用了多个监视器应用程序,例如jconsole和YourProfiler。之后,我尝试在堆转储(Hap Dumps)的帮助下找出问题,我使用jmap对其进行了分析,并使用Eclipse Memory Analyzer进行了分析。

现在,我的问题是,在此示例代码中,哪个选项更好或更不用堆空间1或2?

选项1:

while (true){
byte [] one= new byte [21]; 
do something with one;
byte [] two= new byte [50];
do something with two;
byte [] three= new byte [30];
do something with three;
}

选项2:

byte [] one;
byte [] two;
byte [] three;
while (true){
one= new byte [21]; 
do something with one;
two= new byte [50];
do something with two;
three= new byte [30];
do something with three;
}

我不知道在循环中创建的三个对象会发生什么。这些应该是局部变量,并且仅在循环中可见和可访问。但是在一个循环循环之后,JVM将删除它们并在下一循环中创建一个新循环。我猜应该不会有内存泄漏吗?

在第二个选项中,三个变量在循环外部声明,因此它们在整个时间内都将保持活动状态。在循环中,这些对象的引用发生了变化,因此将没有对旧内容的引用,这意味着旧内容将被删除,分别由GC收集。

在两个选项中,每秒大约有4个圆圈。

预先感谢您的帮助!

JUnit测试的结果:

在此处输入图片说明

安迪·特纳(Andy Turner)

变量onetwothree只是引用:他们不持有的价值本身,而只是指地方在实际的数组对象存储在堆。

这样,就分配的对象数量而言,两种方法之间没有区别。

选项3:在循环外分配数组,然后重用相同的数组:

byte [] one= new byte [21];
byte [] two= new byte [50];
byte [] three= new byte [30];
while (true){
  // If necessary, zero out the arrays so that data from the previous
  // iteration is not used accidentally.
  Arrays.fill(one, (byte) 0);
  Arrays.fill(two, (byte) 0);
  Arrays.fill(three, (byte) 0);

  // Rest of the loop.
}

这将预先分配数组,因此仅创建3个数组对象,而不是(3 * #iterations)数组对象。

请注意,只有在不泄漏对数组的引用的情况下,才可以使用这种方法,例如,将它们放入循环体之外的列表中。


为了证明内存的分配在OP的两种方法中是相同的,请尝试反编译代码:

  public static void inLoop() {
    while (true) {
      byte[] one = new byte[21];
      byte[] two = new byte[50];
      byte[] three = new byte[30];
    }
  }

  public static void outsideLoop() {
    byte[] one;
    byte[] two;
    byte[] three;
    while (true) {
      one = new byte[21];
      two = new byte[50];
      three = new byte[30];
    }
  }

这两个方法反编译为相同的字节码:

  public static void inLoop();
    Code:
       0: bipush        21
       2: newarray       byte
       4: astore_0
       5: bipush        50
       7: newarray       byte
       9: astore_1
      10: bipush        30
      12: newarray       byte
      14: astore_2
      15: goto          0

  public static void outsideLoop();
    Code:
       0: bipush        21
       2: newarray       byte
       4: astore_0
       5: bipush        50
       7: newarray       byte
       9: astore_1
      10: bipush        30
      12: newarray       byte
      14: astore_2
      15: goto          0

因此,运行时内存分配必须相同。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章