String.intern()引起的性能问题

项目代码中用到反射,伴随大量的NoSuchFieldException异常,发现cpu飙高,排查后发现跟String.intern有关。 java

Class中有连个常见的方法: eclipse

Ø public Field getField(String name) this

Ø getMethod(String name, Class<?>... parameterTypes) spa

进入这个方法的实现,发现都会调用searchXXX的方法,已searchFields为例: .net

private Field searchFields(Field[] fields, String name) {

        String internedName = name.intern();

        for (int i = 0; i < fields.length; i++) {

            if (fields[i].getName() == internedName) {

                return getReflectionFactory().copyField(fields[i]);

            }

        }

        return null;

}

注意这里的name.intern()调用,jdoc它的是说明以下: code

A pool of strings, initially empty, is maintained privately by the class String. ip

When the intern method is invoked, if the pool already contains a string equal to this String object as determined by the equals(Object) method, then the string from the pool is returned. Otherwise, this String object is added to the pool and a reference to this String object is returned. 内存

简单的说,String.intern()返回String pool中的引用,若是String pool中不存在,则先在String pool中加入一个字符串而后返回该引用。所以,若是s.equals(t) 是true,则 s.intern() == t.intern() 也为true 字符串

问题来了,因为String pool位于perm区,若是随着String pool愈来愈大,就会引起full gc(只有full gc才会回收perm,另外,perm区的内存在好久好久之前的jdk中是不能被垃圾回收的,jdk1.2之后均可以回收);另外,String poolhashtable(实际是weakreference)当这个table大了之后,不管是插入仍是查找,都会付出愈来愈大的代价。 get

综合上述状况大量调用String.intern()而且大部分未能在string pool中找到已存在的实例,会引起String pool愈来愈大,进而致使intern方法效率下降,当string pool大到必定程度后,还会引起fgc。所以,慎用String.intern。

相关文章
相关标签/搜索