关于 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 文件里的.