从Java应用程序外部传递的String是否会保存在String池中?

时间:2014-08-07 15:06:56

标签: java string string-pool

我读了很多答案,但没有一个能真正回答我的问题。

如果我在某个端口上运行java服务并且客户端连接到它并调用如下方法:

String data = getServiceData("clientKey");

现在我的问题是,这个密钥(clientKey)是否会存储在服务端的String文字池中?一般来说,存储在常量池中的文字是在编译时计算出来的,但是从JVM外部传递的字符串或者在读取文件时可能会发生什么?

2 个答案:

答案 0 :(得分:3)

String对象在客户端序列化并反序列化并保存在堆内存中。如果您希望将其存储在String Pool内存中,则应使用intern()方法。

    String value;
    String data = (value =getServiceData("clientKey"))==null?null:value.intern();

答案 1 :(得分:2)

从外部源(特别是BufferedReader.getLine()或Java序列化)读取字符串的大多数方法都不会实际执行字符串,所以答案是否定的。

但是,如果您使用第三方库,他们可能会这样做:例如,已知有一些XML / Dom解析器(至少对于元素名称,对于值来说较少)。还有一些高性能框架(servlet容器),用于某些字符串(例如HTTP标头名称)。

但通常它很少用于良好的(!)实现,因为它不像人们想象的那么令人满意。不要忘记:在你可以实践一个字符串之前,它必须作为一个需要收集的对象存在,所以从使用intern()避免垃圾的角度来看并没有帮助。如果这些字符串长时间存在(它不在OLTP中)并且可能会稍微加快相等性检查,它只会减少工作集内存。但通常这只有在相同的字符串对象上执行数千个时才有用。

您可以检查自己该字符串是否已被实现(您当然不应该在生产代码中执行此操作,因为它实际上是在您的字符串中,并且它可能在所有实现中都不起作用):

input == input.intern()?"yes":"no"`

是的(如评论中所述),具有相同API密钥的百万个实例可能会发生这种情况。但不要被愚弄认为这是一件坏事。实际上实习他们需要搜索价值并处理不断增长的字符串池。这可能比处理(和释放)字符串花费更长的时间。特别是当JVM可以使用世代分配和转义分析来优化字符串分配时。

BTW:Java 8u20有一个功能(-XX:+UseStringDeduplication -XX:+PrintStringDeduplicationStatistics),用于在G1中进行垃圾收集时检测后台中的重复字符串。它将组合这些字符串数组以减少内存消耗。 (JEP192