方法中字符串变量的jvm优化

时间:2011-04-07 08:01:47

标签: java garbage-collection jvm

在我正在维护的项目中,我发现了一个java类,其方法“fn”类似于下面所示的方法

class Test{

public void fn(){
    String METHOD_NAME = "fn";
    ...
    sysout("In " + METHOD_NAME);
}
}

程序无限期运行,方法'fn'被称为连续且频率非常高。问题是

  1. 每次调用fn()时都会创建变量METHOD_NAME吗?
  2. JVM会进行一些优化,以便变量METHOD_NAME不会被垃圾收集并在下次调用fn()时重用吗?
  3. 如果我将变量设为公共静态决赛,会有性能提升吗? (实际上有很多这样的功能,我想知道它是否值得改变所有这些功能)
  4. (我猜字符串池在这里扮演一些角色)

    谢谢, Kiran Mohan

7 个答案:

答案 0 :(得分:6)

是的,每次输入方法时都会创建变量 METHOD_NAME,但这是一个非常非常便宜的操作(实际上创建2个变量与创建1一样昂贵)

(即String对象)"fn"重新创建,但将来自常量字符串池。

但是,表达式"In " + METHOD_NAME将被重新计算,并且每次都会创建一个新的String对象,因为它不是compile time constant expression。< / p>

如果METHOD_NAMEstatic final,那么该表达式也将是一个编译时常量,因此将来自常量池。

答案 1 :(得分:3)

变量不是垃圾收集 - 对象是。

“fn”是一个字符串文字,因此它将被实习。它不会被垃圾收集(至少在ClassLoader存活的时候;不确定每个CL是否有一个实习池或整个JVM有一个,但它可能不相关)并且每个调用都会使用相同的字符串对象。 / p>

如果你把它作为公共静态决赛,那么肯定是一种改进,因为连接可以由编译器而不是在执行时完成。

如果你在方法中最终(即仍作为局部变量),可能具有相同的效果 - 我不确定。

答案 2 :(得分:2)

“fn”将被实习。因此,将一次又一次地使用相同的对象。

在最坏的情况下,您可以通过以下方式替换它:

String METHOD_NAME = "fn".intern();

虽然我认为这是不必要的。

将其公开为静态决赛是好的。

答案 3 :(得分:1)

据我所知,METHOD_NAME - 对字符串'fn'的引用将在每次调用fn()时分配。但是,字符串'fn'的对象应该被分配一次,因为它是一个String常量,并且将放在String池中。

用公共静态决赛替换它可能是一个好主意,但这是编程风格而不是性能问题。

答案 4 :(得分:0)

字符串文字放在常量池中。将字符串放在静态final中没有任何意义 - 这种行为是由JLS保证的。

(是的,该字符串也将被实习,但这与您的担忧并不特别相关)

答案 5 :(得分:0)

  

每次调用fn()时都会创建变量METHOD_NAME吗?

变量将被“创建”(更好地“设置”)但字符串不是(因为它是驻留在JVM的字符串池中的内化字符串)。所以它只是对同一个字符串的新引用。

  

JVM会进行一些优化,以便变量METHOD_NAME不会被垃圾收集并在下次调用fn()时重用

变量METHOD_NAME只是参考的名称。引用的字符串可能驻留在字符串池中。

  如果我将变量设为公共静态最终版,会不会有性能提升?

可能有,但我宁愿忽略它,因为它将是微优化。

实际上,为了获得较小的性能提升,您应该考虑是否每次都需要打印日志语句,尤其是在可能过于冗长的生产环境中。

答案 6 :(得分:-2)

你去公共静态决赛,这将提高性能。