关于 Java String 拼接

假设我有如下代码:

String result = "!";
for (int i = 0; i < 1000; i++) {
    result += "abc";
}
blackHole.consume(result);

可以看到里面有很多次字符串拼接, 那么这个 String 会被自动优化为 StringBuilder 类型, 使用 append(String) 方法. 具体实现是使用其父类 AbstractStringBuilder 的 append(String) 方法:

    public AbstractStringBuilder append(String str) {
        if (str == null)
            return appendNull();
        int len = str.length();
        ensureCapacityInternal(count + len);
        str.getChars(0, len, value, count);
        count += len;
        return this;
    }

这里的 str.getChars() 就是字符串复制的方法, 就是 String.getChars() 方法, 里面就这么一句重要的:

System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);

System.arraycopy 是 native 实现:

    public static native void arraycopy(Object src,  int  srcPos,
                                        Object dest, int destPos,
                                        int length);

这个 native 实现具体就在 openJDK 的 src/share/vm/prims/jvm.cpp 里面:

JVM_ENTRY(void, JVM_ArrayCopy(JNIEnv *env, jclass ignored, jobject src, jint src_pos,
                               jobject dst, jint dst_pos, jint length))
  JVMWrapper("JVM_ArrayCopy");
  // Check if we have null pointers
  if (src == NULL || dst == NULL) {
    THROW(vmSymbols::java_lang_NullPointerException());
  }
  arrayOop s = arrayOop(JNIHandles::resolve_non_null(src));
  arrayOop d = arrayOop(JNIHandles::resolve_non_null(dst));
  assert(s->is_oop(), "JVM_ArrayCopy: src not an oop");
  assert(d->is_oop(), "JVM_ArrayCopy: dst not an oop");
  // Do copy
  s->klass()->copy_array(s, src_pos, d, dst_pos, length, thread);
JVM_END

在具体下去, 就是在 src/share/vm/oops/objArrayKlass.cpp 里面的 copyarray 方法:

void ObjArrayKlass::copy_array(arrayOop s, int src_pos, arrayOop d,
            int dst_pos, int length, TRAPS) {...}

上面这个方法调用了 do_copy 方法, 里面会根据具体的类型去选择具体的 copy 方法. 如果我们只是上面例子的字母, 应该会选择到 src/share/vm/utilities/copy.hpp 里面的各种具体的 copy 方法:

// Assembly code for platforms that need it.
extern "C" {
  void _Copy_conjoint_words(HeapWord* from, HeapWord* to, size_t count);
  void _Copy_disjoint_words(HeapWord* from, HeapWord* to, size_t count);

  void _Copy_conjoint_words_atomic(HeapWord* from, HeapWord* to, size_t count);
  void _Copy_disjoint_words_atomic(HeapWord* from, HeapWord* to, size_t count);

  void _Copy_aligned_conjoint_words(HeapWord* from, HeapWord* to, size_t count);
  void _Copy_aligned_disjoint_words(HeapWord* from, HeapWord* to, size_t count);

  void _Copy_conjoint_bytes(void* from, void* to, size_t count);

  void _Copy_conjoint_bytes_atomic  (void*   from, void*   to, size_t count);
  void _Copy_conjoint_jshorts_atomic(jshort* from, jshort* to, size_t count);
  void _Copy_conjoint_jints_atomic  (jint*   from, jint*   to, size_t count);
  void _Copy_conjoint_jlongs_atomic (jlong*  from, jlong*  to, size_t count);
  void _Copy_conjoint_oops_atomic   (oop*    from, oop*    to, size_t count);

  void _Copy_arrayof_conjoint_bytes  (HeapWord* from, HeapWord* to, size_t count);
  void _Copy_arrayof_conjoint_jshorts(HeapWord* from, HeapWord* to, size_t count);
  void _Copy_arrayof_conjoint_jints  (HeapWord* from, HeapWord* to, size_t count);
  void _Copy_arrayof_conjoint_jlongs (HeapWord* from, HeapWord* to, size_t count);
  void _Copy_arrayof_conjoint_oops   (HeapWord* from, HeapWord* to, size_t count);
}

============== 从底向上看 ========
最终这些字符走的是(这里是 X86 架构,也有其它架构的) src/cpu/x86/vm/stubGenerator_x86_64.cpp 的 jshort_disjoint_arraycopy 方法, 那么这些 stub 是定义在:

StubRoutines::_jshort_disjoint_arraycopy

上面这个函数是定义在: src/share/vm/runtime/stubRoutines.hpp 文件里的.

标签: none

添加新评论