System.arraycopy底层源码

2024-01-13 05:38
文章标签 源码 底层 system arraycopy

本文主要是介绍System.arraycopy底层源码,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

  • JDK:jdk1.8.0_11
  • OpenJDK:openjdk-8u40-src-b25-10_feb_2015
public static native void arraycopy(Object src,  int  srcPos,Object dest, int destPos,int length);
  • 打开openjdk\hotspot\src\share\vm\prims\jvm.cpp可以看到一个方法JVM_ArrayCopy,但是该方法没有真正实现复制的代码,而是简单的检测源数组和目的数组不为空,排除一些异常情况 /* java.lang.System中的arraycopy方法 */ 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

  • openjdk\hotspot\src\share\vm\oops\objArrayKlass.cpp文件中copy_array方法

/*
java.lang.System中的arraycopy方法具体实现
*/
void ObjArrayKlass::copy_array(arrayOop s, int src_pos, arrayOop d,int dst_pos, int length, TRAPS) {//检测s是数组assert(s->is_objArray(), "must be obj array");//目的数组不是数组对象的话,则抛出ArrayStoreException异常if (!d->is_objArray()) {THROW(vmSymbols::java_lang_ArrayStoreException());}// Check is all offsets and lengths are non negative//检测下标参数非负if (src_pos < 0 || dst_pos < 0 || length < 0) {THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException());}// Check if the ranges are valid//检测下标参数是否越界if  ( (((unsigned int) length + (unsigned int) src_pos) > (unsigned int) s->length())|| (((unsigned int) length + (unsigned int) dst_pos) > (unsigned int) d->length()) ) {THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException());}// Special case. Boundary cases must be checked first// This allows the following call: copy_array(s, s.length(), d.length(), 0).// This is correct, since the position is supposed to be an 'in between point', i.e., s.length(),// points to the right of the last element.//length==0则不需要复制if (length==0) {return;}//UseCompressedOops只是用来区分narrowOop和oop,具体2者有啥区别需要再研究//调用do_copy函数来复制if (UseCompressedOops) {narrowOop* const src = objArrayOop(s)->obj_at_addr<narrowOop>(src_pos);narrowOop* const dst = objArrayOop(d)->obj_at_addr<narrowOop>(dst_pos);do_copy<narrowOop>(s, src, d, dst, length, CHECK);} else {oop* const src = objArrayOop(s)->obj_at_addr<oop>(src_pos);oop* const dst = objArrayOop(d)->obj_at_addr<oop>(dst_pos);do_copy<oop> (s, src, d, dst, length, CHECK);}
}
  • do_copy方法
// Either oop or narrowOop depending on UseCompressedOops.
template <class T> void ObjArrayKlass::do_copy(arrayOop s, T* src,arrayOop d, T* dst, int length, TRAPS) {BarrierSet* bs = Universe::heap()->barrier_set();// For performance reasons, we assume we are that the write barrier we// are using has optimized modes for arrays of references.  At least one// of the asserts below will fail if this is not the case.assert(bs->has_write_ref_array_opt(), "Barrier set must have ref array opt");assert(bs->has_write_ref_array_pre_opt(), "For pre-barrier as well.");if (s == d) {// since source and destination are equal we do not need conversion checks.assert(length > 0, "sanity check");bs->write_ref_array_pre(dst, length);//复制的函数Copy::conjoint_oops_atomic(src, dst, length);} else {// We have to make sure all elements conform to the destination arrayKlass* bound = ObjArrayKlass::cast(d->klass())->element_klass();Klass* stype = ObjArrayKlass::cast(s->klass())->element_klass();if (stype == bound || stype->is_subtype_of(bound)) {// elements are guaranteed to be subtypes, so no check necessary//stype对象是bound,或者stype是bound的子类抑或stype实现bound接口bs->write_ref_array_pre(dst, length);Copy::conjoint_oops_atomic(src, dst, length);} else {// slow case: need individual subtype checks// note: don't use obj_at_put below because it includes a redundant store checkT* from = src;T* end = from + length;for (T* p = dst; from < end; from++, p++) {// XXX this is going to be slow.T element = *from;// even slower nowbool element_is_null = oopDesc::is_null(element);oop new_val = element_is_null ? oop(NULL): oopDesc::decode_heap_oop_not_null(element);if (element_is_null ||(new_val->klass())->is_subtype_of(bound)) {bs->write_ref_field_pre(p, new_val);*p = element;} else {// We must do a barrier to cover the partial copy.const size_t pd = pointer_delta(p, dst, (size_t)heapOopSize);// pointer delta is scaled to number of elements (length field in// objArrayOop) which we assume is 32 bit.assert(pd == (size_t)(int)pd, "length field overflow");bs->write_ref_array((HeapWord*)dst, pd);THROW(vmSymbols::java_lang_ArrayStoreException());return;}}}}bs->write_ref_array((HeapWord*)dst, length);
}
  • 在openjdk\hotspot\src\share\vm\utilities\copy.hpp文件中找到该conjoint_oops_atomic函数,还有针对narrowOop的重载函数,这里不写出 // oops,conjoint, atomic on each oop
static void conjoint_oops_atomic(oop* from, oop* to, size_t count) {assert_params_ok(from, to, LogBytesPerHeapOop);pd_conjoint_oops_atomic(from, to, count);}
  • openjdk\hotspot\src\share\vm\oops\klass.hpp中的is_subtype_of函数
    //检测是否是k的子类,或者是实现k接口
bool is_subtype_of(Klass* k) const {juint    off = k->super_check_offset();Klass* sup = *(Klass**)( (address)this + off );const juint secondary_offset = in_bytes(secondary_super_cache_offset());if (sup == k) {return true;} else if (off != secondary_offset) {return false;} else {return search_secondary_supers(k);}}
  • openjdk\hotspot\src\os_cpu\windows_x86\vm\copy_windows_x86.inline.hpp,最主要就是pd_conjoint_oops_atomic函数
static void pd_conjoint_oops_atomic(oop* from, oop* to, size_t count) {// Do better than this: inline memmove body  NEEDS CLEANUPif (from > to) {while (count-- > 0) {// Copy forwards*to++ = *from++;}} else {from += count - 1;to   += count - 1;while (count-- > 0) {// Copy backwards*to-- = *from--;}}
}

这篇关于System.arraycopy底层源码的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/600406

相关文章

Nacos注册中心和配置中心的底层原理全面解读

《Nacos注册中心和配置中心的底层原理全面解读》:本文主要介绍Nacos注册中心和配置中心的底层原理的全面解读,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录临时实例和永久实例为什么 Nacos 要将服务实例分为临时实例和永久实例?1.x 版本和2.x版本的区别

8种快速易用的Python Matplotlib数据可视化方法汇总(附源码)

《8种快速易用的PythonMatplotlib数据可视化方法汇总(附源码)》你是否曾经面对一堆复杂的数据,却不知道如何让它们变得直观易懂?别慌,Python的Matplotlib库是你数据可视化的... 目录引言1. 折线图(Line Plot)——趋势分析2. 柱状图(Bar Chart)——对比分析3

Android实现一键录屏功能(附源码)

《Android实现一键录屏功能(附源码)》在Android5.0及以上版本,系统提供了MediaProjectionAPI,允许应用在用户授权下录制屏幕内容并输出到视频文件,所以本文将基于此实现一个... 目录一、项目介绍二、相关技术与原理三、系统权限与用户授权四、项目架构与流程五、环境配置与依赖六、完整

Android实现定时任务的几种方式汇总(附源码)

《Android实现定时任务的几种方式汇总(附源码)》在Android应用中,定时任务(ScheduledTask)的需求几乎无处不在:从定时刷新数据、定时备份、定时推送通知,到夜间静默下载、循环执行... 目录一、项目介绍1. 背景与意义二、相关基础知识与系统约束三、方案一:Handler.postDel

Java 正则表达式URL 匹配与源码全解析

《Java正则表达式URL匹配与源码全解析》在Web应用开发中,我们经常需要对URL进行格式验证,今天我们结合Java的Pattern和Matcher类,深入理解正则表达式在实际应用中... 目录1.正则表达式分解:2. 添加域名匹配 (2)3. 添加路径和查询参数匹配 (3) 4. 最终优化版本5.设计思

C#中async await异步关键字用法和异步的底层原理全解析

《C#中asyncawait异步关键字用法和异步的底层原理全解析》:本文主要介绍C#中asyncawait异步关键字用法和异步的底层原理全解析,本文给大家介绍的非常详细,对大家的学习或工作具有一... 目录C#异步编程一、异步编程基础二、异步方法的工作原理三、代码示例四、编译后的底层实现五、总结C#异步编程

Java调用C++动态库超详细步骤讲解(附源码)

《Java调用C++动态库超详细步骤讲解(附源码)》C语言因其高效和接近硬件的特性,时常会被用在性能要求较高或者需要直接操作硬件的场合,:本文主要介绍Java调用C++动态库的相关资料,文中通过代... 目录一、直接调用C++库第一步:动态库生成(vs2017+qt5.12.10)第二步:Java调用C++

Python实现无痛修改第三方库源码的方法详解

《Python实现无痛修改第三方库源码的方法详解》很多时候,我们下载的第三方库是不会有需求不满足的情况,但也有极少的情况,第三方库没有兼顾到需求,本文将介绍几个修改源码的操作,大家可以根据需求进行选择... 目录需求不符合模拟示例 1. 修改源文件2. 继承修改3. 猴子补丁4. 追踪局部变量需求不符合很

Spring 中 BeanFactoryPostProcessor 的作用和示例源码分析

《Spring中BeanFactoryPostProcessor的作用和示例源码分析》Spring的BeanFactoryPostProcessor是容器初始化的扩展接口,允许在Bean实例化前... 目录一、概览1. 核心定位2. 核心功能详解3. 关键特性二、Spring 内置的 BeanFactory

Java的volatile和sychronized底层实现原理解析

《Java的volatile和sychronized底层实现原理解析》文章详细介绍了Java中的synchronized和volatile关键字的底层实现原理,包括字节码层面、JVM层面的实现细节,以... 目录1. 概览2. Synchronized2.1 字节码层面2.2 JVM层面2.2.1 ente