java垃圾收集和临时对象

时间:2014-01-10 12:17:04

标签: java garbage-collection

我是一名c ++开发人员,但我最近做了一点Java。我正在工作的这个项目是由一个开发人员完成的,很久以后我就一直在寻找他正在通过做奇怪事情来处理垃圾收集的事情。

案例和观点他实施了自己的字符串类,以避免因GC而减速

该应用程序的这一部分采用大型二进制文件格式并将其导出到csv。这意味着为文件中的每一行构建一个字符串(数百万)。为了避免这些临时字符串对象,他创建了一个字符串类,它只有一个很大的字节数组,他重复使用。

/**
 HACK
     A Quick and Dirty string builder implementation optimized for GC.
     Using String.format causes the application grind to a halt when
     more than a couple of string operations are performed due to the number of
     temporary objects allocated while formatting strings for drawing or logging.    
*/

这确实有帮助吗?这真的需要吗?这比仅仅在循环外声明一个String对象并将其设置在循环中更好吗?

该应用程序还有一个哈希映射,其中包含值的双精度数。地图中的键是相当静态的,但值经常变化。由于害怕GC上双打,他将myDouble类用作hashmap的值

/**
 *  This is a Mutable Double Wrapper class created to avoid GC issues
 *
 */
public class MyDouble implements Serializable {
    /**
     * 
     */
    private static final long serialVersionUID = C.SERIAL_VERSION_UID;
    public double d;

    public MyDouble(double d) {
        this.d = d;
    }
}

这很疯狂,完全没必要......对吧?

1 个答案:

答案 0 :(得分:3)

字符串连接确实是Java中的瓶颈,因为String是不可变的。这意味着每个连接都会创建一个新的String,除非之前创建了匹配的String,因此它位于字符串池中(请参阅string interning)。无论哪种方式,它肯定会导致问题。

然而,您的前任并不是第一个遇到此问题的人,并且处理在Java中连接许多String的需要的标准方法是使用StringBuilder

当一个double(或者任何一个主要的东西)被用作一个局部变量时,它被保留在堆栈上,它占用的内存与堆栈帧一起被释放(如果它们受到限制,则不确定GC或运行时JVM负责处理)。但是,如果double是对象上的字段,它将存储在堆上,并在收集包含它的对象时收集。

在没有看到如何使用double值的情况下,很难确定,但很可能使用Map会增加GC负载。

总而言之,是的,imho肯定是这样,正如你所说'疯狂且完全没必要'。这些过早的优化只会使代码库变得复杂,使其更容易出错并使将来的维护变得更加困难。黄金法则应该始终如一,构建最简单的工作方式,对其进行分析然后进行优化。