java System.arraycopy() 对应Hotspot里面的源码

java System.arraycopy() 对应Hotspot里面的源码

public class Copy {
    public static void main(String[] args) throws InterruptedException {
        String x = "123456789";
        System.out.println("start");
        Thread.sleep(3000);
        byte[] bytes1 = x.getBytes();
        byte[] bytes = new byte[32];
        System.arraycopy(bytes1, 0, bytes, 0, 8);//本质是将一个内存地址的值复制到另一个内存地址

    }
}
// System.arraycopy 本地方法
 @HotSpotIntrinsicCandidate
    public static native void arraycopy(Object var0, int var1, Object var2, int var3, int var4);

jvm.cpp 307行为本地方法入口


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
//进入klass()->copy_array(s, src_pos, d, dst_pos, length, thread);  
void TypeArrayKlass::copy_array(arrayOop s, int src_pos, arrayOop d, int dst_pos, int length, TRAPS) {
//省略了其他检查逻辑
  int l2es = log2_element_size();
  int ihs = array_header_in_bytes() / wordSize;
  char* src = (char*) ((oop*)s + ihs) + ((size_t)src_pos << l2es);
  char* dst = (char*) ((oop*)d + ihs) + ((size_t)dst_pos << l2es);
  Copy::conjoint_memory_atomic(src, dst, (size_t)length << l2es);
}

下面断点截图同src 地址为 0xff0bd920 值为123456789 确实和java代码里的值一样
dst代表目标地址 地址为 0xff0bd940
在这里插入图片描述

继续进入函数

// Copy bytes; larger units are filled atomically if everything is aligned.
void Copy::conjoint_memory_atomic(void* from, void* to, size_t size) {
  address src = (address) from;
  address dst = (address) to;
  uintptr_t bits = (uintptr_t) src | (uintptr_t) dst | (uintptr_t) size;
//将 要复制数组的内存地址 和目的地址已经长度 进行或运算  在下面根据结果判断 是否是对齐的 8字节对齐 4字节对齐和2直接对齐 这里我刻意拷贝8个字节代码进入第一个分支
  if (bits % sizeof(jlong) == 0) {
    Copy::conjoint_jlongs_atomic((jlong*) src, (jlong*) dst, size / sizeof(jlong));
  } else if (bits % sizeof(jint) == 0) {
    Copy::conjoint_jints_atomic((jint*) src, (jint*) dst, size / sizeof(jint));
  } else if (bits % sizeof(jshort) == 0) {
    Copy::conjoint_jshorts_atomic((jshort*) src, (jshort*) dst, size / sizeof(jshort));
  } else {
    // Not aligned, so no need to be atomic.
    Copy::conjoint_jbytes((void*) src, (void*) dst, size);
  }
}

  // bytes, jshorts, jints, jlongs, oops

  // bytes,                 conjoint, not atomic on each byte (not that it matters)
  static void conjoint_jbytes(void* from, void* to, size_t count) {
    pd_conjoint_bytes(from, to, count);
  }

static void pd_conjoint_jlongs_atomic(jlong* from, jlong* to, size_t count) {
#ifdef AMD64
  _Copy_conjoint_jlongs_atomic(from, to, count);

接着进入

在这里插入图片描述

执行到jbe 0x9e6fa6会进入真正的拷贝逻辑 (注意此时 rax寄存器和rdi 寄存器里面保存的 要复制的内存地址的值)
下面是真正的复制逻辑 此时rsi寄存器的值还为改变 当执行完 movq 0x8(%rax,%rdx,8), %rsi 高亮的代码后rsi里面回存放要复制的值(12345678)刚好为8个字节
在这里插入图片描述
执行结果 rsi 已经为要复制的值 0x3837363534333231 这里为什么不是12345678呢 因为 12345678的asc编码就是3132333435363738

movq %rsi,0x8(%rcx,%rdx,0) 的意思是将rsi寄存器里面的值给到 目标的内存地址 也就是 0xff0bd940 (从下方的调试窗口给出的寄存器值手动计算也是这个值)
在这里插入图片描述
这里我们输出一下 0xff0bd940 的值

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值