Java字符串:内存如何处理不可变字符串

Java字符串:内存如何处理不可变字符串,java,android,string,memory-management,stringbuffer,Java,Android,String,Memory Management,Stringbuffer,我有一个简单的问题 byte[] responseData = ...; String str = new String(responseData); String withKey = "{\"Abcd\":" + str + "}"; 在上面的代码中,这三行占用了3倍的内存。例如,如果响应数据为1mb,则第2行将在内存中额外占用1mb,第3行将额外占用1mb+xx。这是真的吗?如果没有,那么它将如何工作。如果是,那么解决这个问题的最佳方法是什么。StringBuffer在这里有用吗?是的,听

我有一个简单的问题

byte[] responseData = ...;
String str = new String(responseData);
String withKey = "{\"Abcd\":" + str + "}";

在上面的代码中,这三行占用了3倍的内存。例如,如果响应数据为1mb,则第2行将在内存中额外占用1mb,第3行将额外占用1mb+xx。这是真的吗?如果没有,那么它将如何工作。如果是,那么解决这个问题的最佳方法是什么。StringBuffer在这里有用吗?

是的,听起来差不多。可能更大,因为1MB字节数组需要转换为UTF-16,因此根据编码的不同,它可能更大(如果输入为ASCII,则为2MB)

请注意,垃圾收集器可以在使用它的变量超出范围时立即回收内存。您可以尽可能早地将它们设置为
null
,以帮助它尽可能及时地进行设置(例如,在构建字符串后
responseData=null;

如果是,那么解决这个问题的最佳方法是什么

“修复”意味着一个问题。如果你有足够的内存,就不会有问题


问题是,由于来自服务器的字节[]数据相当大,所以我正在退出MemoryException


如果不这样做,您必须考虑一个更好的替代方案,以在内存中保留1MB字符串。也许你可以把数据从文件中流出来?或者直接处理字节数组?这是什么样的数据?

是的,听起来差不多。可能更大,因为1MB字节数组需要转换为UTF-16,因此根据编码的不同,它可能更大(如果输入为ASCII,则为2MB)

请注意,垃圾收集器可以在使用它的变量超出范围时立即回收内存。您可以尽可能早地将它们设置为
null
,以帮助它尽可能及时地进行设置(例如,在构建字符串后
responseData=null;

如果是,那么解决这个问题的最佳方法是什么

“修复”意味着一个问题。如果你有足够的内存,就不会有问题


问题是,由于来自服务器的字节[]数据相当大,所以我正在退出MemoryException


如果不这样做,您必须考虑一个更好的替代方案,以在内存中保留1MB字符串。也许你可以把数据从文件中流出来?或者直接处理字节数组?这是什么样的数据

问题是,由于来自服务器的
byte[]
数据很大,我正在从内存异常中获取
OutOfMemoryException
,这就是为什么我需要首先找出我做错了什么

对。基本上,你的基本问题是,你试图一次将整个字符串保存在内存中。对于足够大的字符串,这总是会失败。。。即使您以尽可能最佳的内存效率方式编写它。(这本身就很复杂。)

最终解决方案(即“缩放”)是执行以下操作之一:

  • 将数据流传输到文件系统,或

  • 以这样一种方式处理它,您永远不需要表示整个“字符串”


您询问
StringBuffer
是否有帮助。这可能会有点帮助。。。只要你正确使用它。诀窍是确保预先分配
StringBuffer
(实际上
StringBuilder
更好!!)足够大,可以容纳所需的所有字符。然后使用字符集解码器(直接或使用读取器管道)将数据复制到其中

但是,即使使用最佳编码,您也可能需要一个3倍于输入大小的峰值
byte[]


请注意,您的OOME问题可能与GC或存储泄漏无关。它实际上是关于您正在使用的数据类型的基本空间要求。。。事实上,Java不提供“字节字符串”数据类型

问题是,由于来自服务器的
byte[]
数据很大,我正在从内存异常中获取
OutOfMemoryException
,这就是为什么我需要首先找出我做错了什么

对。基本上,你的基本问题是,你试图一次将整个字符串保存在内存中。对于足够大的字符串,这总是会失败。。。即使您以尽可能最佳的内存效率方式编写它。(这本身就很复杂。)

最终解决方案(即“缩放”)是执行以下操作之一:

  • 将数据流传输到文件系统,或

  • 以这样一种方式处理它,您永远不需要表示整个“字符串”


您询问
StringBuffer
是否有帮助。这可能会有点帮助。。。只要你正确使用它。诀窍是确保预先分配
StringBuffer
(实际上
StringBuilder
更好!!)足够大,可以容纳所需的所有字符。然后使用字符集解码器(直接或使用读取器管道)将数据复制到其中

但是,即使使用最佳编码,您也可能需要一个3倍于输入大小的峰值
byte[]



请注意,您的OOME问题可能与GC或存储泄漏无关。它实际上是关于您正在使用的数据类型的基本空间要求。。。事实上,Java不提供“字节字符串”数据类型。

在我的apidocs中没有这样的
OutOfMemoryException
。如果它是
OutOfMemoryError
,尤其是在服务器端,那么肯定会有问题

当您收到来自客户端的
big
请求时,那些
String
相关语句不是第一个问题。将3X减少到1X不是解决方案

很抱歉,没有进一步的代码我帮不了你

使用后端存储

您不应该将整个请求正文存储在
字节[]
上。您可以存储
copy stream from request to back-end with small chunked buffer
response.getWriter().write("{\"Abcd\":");
copy <your back-end stored data as stream>);
response.getWriter().write("}");