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

Easter79
• 阅读 1028

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

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

Ø public Field getField(String name)

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

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

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它的是说明如下:

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

When the intern method is invoked, if the pool already contains a string equal to this String object as determined by the [equals(Object)](http://my.oschina.net/u/1162189/admin/eclipse-javadoc:?=coupon-dev/G:\/Program Files/Java/jdk1.6.0_33/jre/lib/rt.jar<java.lang(String.class?String~intern??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 pool是hashtable(实际是weakreference)当这个table大了以后,无论是插入还是查找,都会付出越来越大的代价。

综合上述情况大量调用String.intern()并且大部分未能在string pool中找到已存在的实例,会引发String pool越来越大,进而导致intern方法效率降低,当string pool大到一定程度后,还会引发fgc。因此,慎用String.intern。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
3年前
java将前端的json数组字符串转换为列表
记录下在前端通过ajax提交了一个json数组的字符串,在后端如何转换为列表。前端数据转化与请求varcontracts{id:'1',name:'yanggb合同1'},{id:'2',name:'yanggb合同2'},{id:'3',name:'yang
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Stella981 Stella981
3年前
Hive 删除行, 表 ,清空表
删除行A表数据如下id(String)       name(String)\1                       aaa2                      bbb3                      ccc\
Stella981 Stella981
3年前
Python+Selenium自动化篇
本篇文字主要学习selenium定位页面元素的集中方法,以百度首页为例子。0.元素定位方法主要有:id定位:find\_element\_by\_id('')name定位:find\_element\_by\_name('')class定位:find\_element\_by\_class\_name(''
Stella981 Stella981
3年前
HIVE 时间操作函数
日期函数UNIX时间戳转日期函数: from\_unixtime语法:   from\_unixtime(bigint unixtime\, string format\)返回值: string说明: 转化UNIX时间戳(从19700101 00:00:00 UTC到指定时间的秒数)到当前时区的时间格式举例:hive   selec
Wesley13 Wesley13
3年前
Unity横屏
Android下发现Unity里面的Player设置,并不能完全有效,比如打开了自动旋转,启动的时候还是会横屏,修改XML添加以下代码<applicationandroid:icon"@drawable/ic\_launcher"                    android:label"@string/app\_name"
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
35岁是技术人的天花板吗?
35岁是技术人的天花板吗?我非常不认同“35岁现象”,人类没有那么脆弱,人类的智力不会说是35岁之后就停止发展,更不是说35岁之后就没有机会了。马云35岁还在教书,任正非35岁还在工厂上班。为什么技术人员到35岁就应该退役了呢?所以35岁根本就不是一个问题,我今年已经37岁了,我发现我才刚刚找到自己的节奏,刚刚上路。
Easter79
Easter79
Lv1
今生可爱与温柔,每一样都不能少。
文章
2.8k
粉丝
5
获赞
1.2k