Метод clone(); для массивов

100
29 марта 2022, 21:20

Можно ли где-то посмотреть исходники (как реализован метод) clone() для массива?

Правильно ли я понимаю, что используется нативный метод класса Object для клонирования массива?

Answer 1

Правильно ли я понимаю, что используется нативный метод класса Object для клонирования массива?

Да, согласно спецификации (§10.7) массивы переопределяют метод Object.clone и члены массива эквивалентны членам следующего класса:

class A<T> implements Cloneable, java.io.Serializable {
    public final int length = X;
    public T[] clone() {
        try {
            return (T[])super.clone();
        } catch (CloneNotSupportedException e) {
            throw new InternalError(e.getMessage());
        }
    }
}

Как видно используется вызов Object.clone.

Можно ли где-то посмотреть исходники (как реализован метод) clone() для массива?

Как @dmtr уже написал в комментариях, на этот вопрос уже дали ответ на английском: Is it possible to find the source for a Java native method?.

Вот ссылка на исходники (C++): http://hg.openjdk.java.net/jdk/jdk14/file/2a0de7812409/src/hotspot/share/prims/jvm.cpp#l682

А вот и сам код:

JVM_ENTRY(jobject, JVM_Clone(JNIEnv* env, jobject handle))
  JVMWrapper("JVM_Clone");
  Handle obj(THREAD, JNIHandles::resolve_non_null(handle));
  Klass* klass = obj->klass();
  JvmtiVMObjectAllocEventCollector oam;
#ifdef ASSERT
  // Just checking that the cloneable flag is set correct
  if (obj->is_array()) {
    guarantee(klass->is_cloneable(), "all arrays are cloneable");
  } else {
    guarantee(obj->is_instance(), "should be instanceOop");
    bool cloneable = klass->is_subtype_of(SystemDictionary::Cloneable_klass());
    guarantee(cloneable == klass->is_cloneable(), "incorrect cloneable flag");
  }
#endif
  // Check if class of obj supports the Cloneable interface.
  // All arrays are considered to be cloneable (See JLS 20.1.5).
  // All j.l.r.Reference classes are considered non-cloneable.
  if (!klass->is_cloneable() ||
      (klass->is_instance_klass() &&
       InstanceKlass::cast(klass)->reference_type() != REF_NONE)) {
    ResourceMark rm(THREAD);
    THROW_MSG_0(vmSymbols::java_lang_CloneNotSupportedException(), klass->external_name());
  }
  // Make shallow object copy
  const int size = obj->size();
  oop new_obj_oop = NULL;
  if (obj->is_array()) {
    const int length = ((arrayOop)obj())->length();
    new_obj_oop = Universe::heap()->array_allocate(klass, size, length,
                                                   /* do_zero */ true, CHECK_NULL);
  } else {
    new_obj_oop = Universe::heap()->obj_allocate(klass, size, CHECK_NULL);
  }
  HeapAccess<>::clone(obj(), new_obj_oop, size);
  Handle new_obj(THREAD, new_obj_oop);
  // Caution: this involves a java upcall, so the clone should be
  // "gc-robust" by this stage.
  if (klass->has_finalizer()) {
    assert(obj->is_instance(), "should be instanceOop");
    new_obj_oop = InstanceKlass::register_finalizer(instanceOop(new_obj()), CHECK_NULL);
    new_obj = Handle(THREAD, new_obj_oop);
  }
  return JNIHandles::make_local(env, new_obj());
JVM_END

Обратите внимание на обработку условия obj->is_array() при выделении памяти.

READ ALSO
Использование классов из /target

Использование классов из /target

Я использую JOOQJOOQ генерирует метаклассы, которые потом используются для генерации запросов в базу

128
Как запустить java + selenium + cucumber на windows-сервере

Как запустить java + selenium + cucumber на windows-сервере

Я меня есть windows-сервер, на котором через консоль должны запускаться автотесты (Java, Cucumber, Selenium), которые написаны в IntelliJ IDEA (+maven) на mac osСейчас...

132
Где должен быть родительский файл pom.xml

Где должен быть родительский файл pom.xml

Создал проект с 2 модулями и хотел сделать родительский pom чтобы не писать все дважды, не знаю где должен быть родительский помЗаранее спасибо

68
Конструкторы Java (Модификатор доступа)

Конструкторы Java (Модификатор доступа)

Я еще совсем зеленый в JavaВопрос: какой модификатор доступа имеет конструктор класса, если не указать его

143