我正确地实习了我的弦乐吗?

时间:2009-05-29 06:03:07

标签: java memory-management

我想确保我不会打击permgen空间,所以我小心翼翼地实习我的琴弦。

这两个陈述是否相同?

String s1 = ( "hello" + "world" ).intern(); 

String s2 = "hello".intern() + "world".intern();

更新

我如何构思我的问题与实际应用完全不同。这是我使用实习生的方法。

public String toAddress( Transport transport )
{
    Constraint.NonNullArgument.check( transport, "transport" );

    switch( transport )
    {
    case GOOGLE:
    case MSN:
        return ( transport.code() + PERIOD + _domain ).intern();
    case YAHOO:
    default:
        return _domain;
    }
}
private String _domain;  // is initialized during constructor
private static final String PERIOD = ".";

9 个答案:

答案 0 :(得分:10)

我能想到的最好的建议是:不要打扰。除非你动态创建一个字符串,否则静态声明的字符串将在常量池中,除非你动态创建一个字符串,否则我无法想到原因。

我从97年开始使用Java进行编程,而且我从未实际使用过String.intern()

编辑:看到你的更新后我真的认为你不应该使用intern()。您的方法看起来很正常,并且很少或没有理由使用intern()。

我之所以这样做是因为它会影响优化并且可能是一个过早的优势,你是第二个猜测垃圾收集器。如果你的方法是短暂的,那么结果字符串将很快在下一个小GC中死于年轻一代,如果它不是它将在成熟一代无论如何被插入(因为想要一个更好的词)

我想唯一一次这可能是一个好主意,如果你花了一些时间在一个分析器上并证明它对你的应用程序的性能有很大影响。

答案 1 :(得分:10)

正如jensgram所说,这两个陈述并不相同。两条重要规则:

  • 在代码中连接字符串文字以字符串常量结束,因此这两个语句 完全等效(它们将产生相同的字节码):

    String x = "foo" + "bar":
    String x = "foobar";
    
  • 字符串常量自动实现,您无需明确执行

现在,这集中在文字上 - 你实际上在文字上调用intern,或者你的真实用例有些不同(例如从数据库中获取的内部值,你会看到经常)?如果是这样,请提供更多详细信息。

编辑:好的,基于问题编辑:这个可以保存一些内存如果你最终将toAddress()的返回值存储在它的某个地方我会坚持很长时间你会多次使用相同的地址。如果那些不是的话,实习可能会让事情变得更糟。我不确定被拘禁的琴弦是否永远存在,但这很有可能。

这让我觉得好像不太可能善用实习,很可能会让事情变得更糟。你提到试图挽救permgen空间 - 为什么你相信实习会有帮助呢?无论如何,连接的字符串不会以permgen结尾,除非我错了。

答案 2 :(得分:7)

没有。将两个固定的字符串添加在一起并不会为您提供一个实习字符串。

那就是说,很少有人需要“小心翼翼地实习”。除非你处理大量相同的字符串,否则它比它的价值更麻烦。

答案 3 :(得分:2)

我会说不。 s1将“helloworld”添加到池中,而s2由两个汇集的字符串“hello”和“world”组成。

答案 4 :(得分:2)

更多信息将帮助我们了解您的查询...无论如何......

如果您手动想要为HelloWorld实习,那么请使用第一个语句,如第二个语句中分别实习hello和world。两个陈述完全不相同。

答案 5 :(得分:2)

在编写所有代码之前,您可能希望获得某种形式的证明(通过概要分析),即“扼杀permgen空间”。

否则你可能只是在做“过早优化”,这通常是不赞成的。 有关为什么这可能是一件坏事的详细信息,请参阅http://en.wikipedia.org/wiki/Optimization_(computer_science)#When_to_optimize

答案 6 :(得分:0)

在许多情况下,“仔细实习”你的琴弦只会浪费一些时间。 考虑以下情况:

void foobar(int x) {
  String s1 = someMethod(x).intern();
  ...
  ...
}

所以s1被实习,没有浪费(堆)空间?错误!最有可能的是,someMethod(x)的中间结果仍然存在于堆上的某个地方,需要进行垃圾回收。那是因为someMethod()以某种方式构造了字符串,并且(除非它返回一个文字)它在堆上做了。但那么......更好地查看permgen空间的用途。它用于关于类的元数据和(ooops)String.intern表。通过实习你的所有字符串,你正在做你想要避免的事情:打击permgen空间。

此处提供更多信息:http://www.thesorensens.org/2006/09/09/java-permgen-space-stringintern-xml-parsing/

答案 7 :(得分:0)

您正在使用的字符串数量对JVM的Permananent生成具有 no 效果,因为我们仍在讨论一个

答案 8 :(得分:0)

实习字符串基本上是等待发生的内存泄漏:(

除非你有一个非常非常好的理由[1]不这样做,但是把它留给JVM。

[1]如同,“亲爱的老板,请不要解雇我。我有这个分析数据来支持我决定使用实习生”:)