1
SpicyCat 2016-03-25 11:39:44 +08:00
题目没看懂。
是说一个字符串长度是 1024 ,然后能不能执行 substring 方法一万次? |
2
Jelen 2016-03-25 11:44:52 +08:00
完全没看懂这题
|
3
incompatible 2016-03-25 12:02:41 +08:00 1
substring 会生成新的字符串。由于 java.lang.String 的特殊性,每个生成的字符串都会在永久代里产生一个字符串常量(当一万次调用每次采用的都是不同的 startIndex 和 endIndex 时)。如果启动 jvm 时为永久代分配的空间不够多,那么就会产生 OutOfMemoryError
所以我猜这道题考察的主要是 String 的 intern 以及 jvm 内存模型方面的知识。 ps :以上是针对 jdk6 来说的。 jdk7 和 jdk8 中的变化可以参考下面这个文章: http://java-performance.info/string-intern-in-java-6-7-8/ |
4
incompatible 2016-03-25 12:13:58 +08:00 1
抱歉,以上关于 String.substring()会在永久代产生字符串常量的说法是错误的。 substring 只会在堆内分配新空间,不会在永久代分配空间。
|
5
Infernalzero 2016-03-25 13:49:13 +08:00 2
首先得看是 jdk6 还是 7
不同的版本 subString 方法的实现是不同的 6 里面 subString 会保存原 String 对象的引用,如果大字符串截取少量 String 会浪费很多内存 7 里面就是用 Arrays.copyOfRange 了 主要就是看 public String(char value[], int offset, int count)这个构造方法 总之,具体得看使用场景了,根据要截取的字符串大小和原字符串的比较来判断用哪种方式 |
6
Fred84 2016-03-25 14:14:29 +08:00
假设 1024 个字符串的对象为 a ,每次调用 a.substring 返回的字符串对象会保留 a 对象内存的引用(详见 substring 源码),如果调用了 1 万次,每次调用完毕后没有及时释放(比如你把这些对象都放在一个全局容器中),那么很可能会出现 OOM 的错误。
|
8
li00li OP @incompatible 谢谢
|
9
SoloCompany 2016-03-26 15:03:50 +08:00
你说 intern 会进入 PermGen/MetaSpace 还好理解, substring 甚至是 new String 就是个普通对象操作和 PermGen/MetaSpace 有什么直接关联吗, 唯一有的坑仅仅是 Java 7 开始 substring 的实现不再是 o(0) 而是有了 o(n) 的复制, 因为委员会认为这一点点复制的性能消耗在大多数情况下基本可以忽略, 为了避免对一个很大的字符串进行 substring 的时候因为保留着源字符串内部缓冲区的引用而无法释放内存而可能产生的问题, 并且这个选择是无法由 API 的使用者自己区决定的
|