ITPub博客

首页 > IT职业 > IT图书 > java string中的比较难注意细节(intern,subStri

java string中的比较难注意细节(intern,subStri

IT图书 作者:cylong 时间:2021-09-09 09:12:30 0 删除 编辑

    jdk1.6后对字符串常量池做了改动,从源码到表现都做了很多改动。都是在规避了OOM的问题。下面说一些改动细节以及一些常见的错误认识。

https://my.oschina.net/xpbob/blog/751405

String的1.6的表现以及场景问题:https://my.oschina.net/xpbob/blog/746488

    主要变动就是字符串常量池的位置发生了改变,由方法区转化到了堆中。intern返回的是堆中的第一次出现且intern的字符串的String对象。

    intern的操作最后参考SymbolTable.cpp中的intern方法,1.6和1.7都是这个。

String的gc

    这个细节是上intern的变动发现的。

    最开始我的理解是字符串常量基本不会被回收,只会随着类的回收而回收。事实情况不是这样的。

public static void main(String[] args) {
    show();
    System.gc();
    show();

}

public static void show(){
    String s =new String(new char[]{'a','b'});
    System.out.println(System.identityHashCode(s));
    System.out.println(System.identityHashCode(s.intern()));
}

    上面这段代码最好在jdk1.7以上执行,效果比较明显,你会发现,show方法中字符串ab和常量池中的ab的地址是一样的(这里说object是hashcode基本等同于地址,虽然事实并不是,只是和重写的hash来做区分),如果没有执行gc,那么结果都是常量池中的ab总会和第一次新建的ab的地址保持一致。

    最开始我以为是gc的时候from到to区域,所以地址变了,仔细调试看了唯一Id发现不是。

    intern的字符串被gc掉了。因为最初网上有用Intern来把字符串放入常量池来减少保证地址比较相同的做法。这个做法没什么问题。只是如果要保存地址值来做标识,那就会出问题了。

    回收的代码,1.6和1.7也是有点不同的。

    1.6的代码在SymbolTable.hpp中的unlink方法。

    1.7的代码在SymbolTable.cpp中的unlink方法。

    都是在gc执行的时候操作。只要没有堆栈对这个string持有引用,就可以被回收,这样就避免了太多的字符串加入到常量池中,把常量池所在的区域给oom了。

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/2005/viewspace-2800572/ ,如需转载,请注明出处,否则将追究法律责任。

下一篇: 斐波拉契数列
请登录后发表评论 登录
全部评论

注册时间:2019-04-16

  • 博文量
    106
  • 访问量
    1360