内存关注处理大字符串

时间:2017-01-07 08:19:56

标签: java string memory memory-management jvm

在我的应用程序中,我编写了一个REST调用,仅供开发人员和支持人员使用,它从日志文件加载n大小的数据并将其作为text / plain返回,其中n是可配置的数字,不能超过固定大小。

    RandomAccessFile file = new RandomAccessFile(logFinalPath, "r");
    //chunk default is 100000 max is 500000
    chunk = chunk <=0l?100000:(chunk>500000?500000:chunk);
    long fileSize = file.length();
    //start position is either chunk size from the end or when the file is smaller then from the beginning of file
    long pos = fileSize>chunk?file.length()-chunk:0;    
    int maxSize = (int) (fileSize>chunk?chunk:fileSize);
    file.seek(pos);
    byte[] bytes = new byte[maxSize];
    file.read(bytes);
    file.close();
    logger.info("fileSize : "+fileSize);
    return new String(bytes);

现在我的问题是,我们知道String是不可变的,并且创建的任何新String都会进入字符串池,直到JVM打开并运行为止。那么在这种情况下,每次进行这个REST调用都不会对内存产生影响,因为它会继续将大文本加载到字符串池中吗?

如果是,有什么替代方案,我无法传递字节数组,因为这是不可读的。怎么会更好?

更新:请注意,这个问题不是关于String或文字表示的新构造函数,而是关于如何对其进行优化以避免将大型String存储到字符串池中,无论是否存在来自堆对象的引用。

1 个答案:

答案 0 :(得分:0)

  

我们知道String是不可变的

  

并且创建的任何新String都会进入String pool

不,除非您致电String.intern()

  

在JVM打开并运行之前永远不要清理。

当字符串文字被移动到堆中时,可以从Java 6中清除字符串文字。

  

那么在这种情况下,每次进行这个REST调用都不会对内存产生影响,因为它会继续将大文本加载到字符串池中吗?

大型物品被添加到终身空间中并清理它们,您需要一个通常要避免的主要集合。

性能损失很小,但没有像将byte[]转换为字符串那么大,只是为了稍后将其转换回字节。通过将缓存的数据保持为byte[]

,可以节省大量工作(和内存)

我很想在启动时将源文件存储到内存中(无论文件有多大,它几乎不使用堆)并根据需要从源文件目录复制到请求的输出并避免接通堆尽可能地复制。