Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/solr/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 处理大字符串的内存问题_Java_String_Memory_Memory Management_Jvm - Fatal编程技术网

Java 处理大字符串的内存问题

Java 处理大字符串的内存问题,java,string,memory,memory-management,jvm,Java,String,Memory,Memory Management,Jvm,在我的应用程序中,我编写了一个REST调用,该调用只供开发人员和支持人员使用,它从日志文件加载n个大小的数据,并以文本/普通形式返回,其中n是一个可配置的数字,不能超过固定大小 RandomAccessFile file = new RandomAccessFile(logFinalPath, "r"); //chunk default is 100000 max is 500000 chunk = chunk <=0l?100000:(chunk>50000

在我的应用程序中,我编写了一个REST调用,该调用只供开发人员和支持人员使用,它从日志文件加载n个大小的数据,并以文本/普通形式返回,其中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);
RandomAccessFile文件=新的RandomAccessFile(logFinalPath,“r”);
//区块默认值为100000,最大值为500000
区块=区块500000?500000:区块);
long fileSize=file.length();
//开始位置是从文件末尾开始的块大小,或者当文件小于文件开头时的块大小
long pos=fileSize>chunk?file.length()-chunk:0;
int maxSize=(int)(文件大小>区块?区块:文件大小);
文件搜索(pos);
字节[]字节=新字节[maxSize];
文件读取(字节);
file.close();
info(“fileSize:+fileSize”);
返回新字符串(字节);
现在是我的问题,我们知道字符串是不可变的,创建的任何新字符串都会进入字符串池,在JVM启动并运行之前都不会被清除。所以,在这种情况下,每次调用REST时,它会一直将大文本加载到字符串池中,这难道不是对内存的一种冲击吗

如果是,有什么替代方案,我不能传递字节数组,因为那样将无法读取。怎样才能更好呢

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

我们知道字符串是不可变的

创建的任何新字符串都将进入字符串池

不,除非调用
String.intern()

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

当字符串文本被移动到堆中时,可以从Java6中清除字符串文本

所以,在这种情况下,每次调用REST时,它会一直将大文本加载到字符串池中,这难道不是对内存的一种冲击吗

将大型对象添加到永久空间中,为了清理这些对象,您需要一个通常希望避免的大型集合

性能受到的影响很小,但不如将
字节[]
转换为字符串后再将其转换回字节那么大。通过将缓存的数据保留为
字节[]


我会尝试在启动时内存映射源文件(无论文件有多大,它几乎不使用堆),并根据需要从源文件目录复制到请求的输出,尽可能避免使用堆上的副本。

可能重复感谢Peter的响应,我得到了我的“假设”,即所有字符串都进入字符串池是没有根据的和错误的,最终这些大字符串将被收集。我无法缓存字节[],因为日志文件不断写入,我想说最后100行。内存映射只是一个概念,我不确定是否适用于滚动文件,我的意思是日志文件作为新文件滚动,每天滚动一次,或者说当它变大200MB时滚动一次。@RahulKumar我们使用内存映射来滚动文件,但我们控制生产者和消费者。如果您不是生产者,那么内存映射将很棘手。语句“字符串文本可以从Java 6中清除,因为字符串文本被移动到堆中”是误导性的。字符串总是像任何其他对象一样接受垃圾收集。“永久生成”的问题是它有一个固定的大小,而不是它从来没有被GC’ed。它特别容易引起误解,因为问题不是关于文本,对字符串对象调用
intern()
会将其添加到池中,但不会将其转换为文本。由于此类手动添加的池字符串不与类关联,因此它们始终可以被垃圾收集(在每个Java版本中)。