读”Java 性能优化之 String 篇“有感
读了 IBM Developer Works上的一篇 Java 性能优化之 String 篇 感觉写得比较实用,但也有一些问题值得斟酌:
1)关于内存空间的使用大小,虽然Java的基本类型的大小是固定的,不因运行环境而变化,但是Object overhead,以及Reference的大小是与平台相关的,比如在64bit的机器上Object overhead 应该是16 bytes,Reference是8bytes,这点应该说清楚。特别是作者是2012年发表的此文,这时应该64bit的系统比较普及了。
2)作者提到用如下方法重新构建子串,从原释放原来字符串的空间:
String newString = new String(smallString.toCharArray());
个人认为,这个不是个好方法,道先 toCharArray()会拷贝一次char[],但 new String(char[] value) 会再拷贝一次:
public String(char value[]) { int size = value.length; this.offset = 0; this.count = size; this.value = Arrays.copyOf(value, size); }
比较好的方法是:
String newString = new String(smallString);
看一下这个构造函数的原代码就知道了:
public String(String original) { int size = original.count; char[] originalValue = original.value; char[] v; if (originalValue.length > size) { // The array representing the String is bigger than the new // String itself. Perhaps this constructor is being called // in order to trim the baggage, so make a copy of the array. int off = original.offset; v = Arrays.copyOfRange(originalValue, off, off+size); } else { // The array representing the String is the same // size as the String, so no point in making a copy. v = originalValue; } this.offset = 0; this.count = size; this.value = v; }
3) 作者提到:
使用 String 的 intern()
方法返回 JVM 对字符串缓存池里相应已存在的字符串引用,从而解决内存性能问题,但这个方法并不推荐!原因在于:首先, intern()
所使用的池会是 JVM 中一个全局的池,很多情况下我们的程序并不需要如此大作用域的缓存;其次,intern() 所使用的是 JVM heap 中 PermGen 相应的区域,在 JVM 中 PermGen 是用来存放装载类和创建类实例时用到的元数据。程序运行时所使用的内存绝大部分存放在 JVM heap 的其他区域,过多得使用 intern()
将导致 PermGen 过度增长而最后返回 OutOfMemoryError
,因为垃圾收集器不会对被缓存的 String 做垃圾回收。
他建议自己建一个 String Cache,但这个Cache也同样是点用了堆的(在new Gen或者Old Gen中),而且何时释放,怎么释放也很重要,如果用强引用也是不会被回收的。而Perm Gen虽然不会被回收,也是可以通过JVM来调节大小的。所以作者的理由不是很充分。我建议可以用Soft Reference来建这个自定义的String Cache。
已有 0 人发表留言,猛击->> 这里<<-参与讨论
ITeye推荐