17

The clone method on Object, which creates an exact copy of an object, is declared as:

protected native Object clone() throws CloneNotSupportedException;

Why is it native?

Bhargav Modi
  • 2,605
  • 3
  • 29
  • 49
Aamir
  • 2,380
  • 3
  • 24
  • 54
  • 3
    Please unbold your question. – Maroun Dec 01 '14 at 08:47
  • 7
    Related (duplicate?): http://stackoverflow.com/a/557606/1225328 – sp00m Dec 01 '14 at 08:54
  • That question doesn't really have a conclusive answer for why *clone* is native, just someone's guess. – Chris Martin Dec 01 '14 at 08:58
  • Agreed. I've nominated to reopen. There's a huge difference between "what is `native`" and "why is this method declared `native`"? – Chris Hayes Dec 01 '14 at 09:02
  • 1
    Since cloning doesn't use constructor in order to create a copy of the object and since `clone` method creates a clone by invoking `super.clone()` which will call Object's `clone` method, it *must* be native in order to create *new* and equal object. – Maroun Dec 01 '14 at 09:31

4 Answers4

13

Basically, because the clone() method does something that you cannot do in the Java language: it clones the state the of the object, including its actual class designation.

The cloning mechanism in Java is based on each class calling the superclass's clone method, all the way up to Object. Object then uses this "magical" native clone method to duplicate the original object, including its actual class.

Think of this:

class A implements Cloneable {

    public A clone() {

        A obj = (A) super.clone();

        // Do some deep-copying of fields

        return obj;
    }

}

class B extends A {

    public B clone() {

        B obj = (B) super.clone();

        // Do some deep-copying of fields not known to A

        return obj;

    }
}

Now imagine that you have a B type object, and you call clone on it. You expect to get a B object, whose class is internally recognized as B, not as Object. B doesn't know the implementation of everything in A, and therefore it needs to call A's clone method. But if A implemented clone in the Java language rather than calling super.clone(), then the object it would return would have to be A. It cannot use new B() (assume B was not known when A was created).

It could do something with reflection, but how would it know which constructor to call so that all the final fields would be properly filled up?

So the trick is that A doesn't do it itself, it calls super.clone(), and this goes all the way back to Object, and it uses a native method that does a byte-by-byte copying of the original object, adjusting for the new heap location. Thus, the new object magically becomes a B object and the type casting would not fail.

Why not return an Object then? Because that would not be cloning. When you call clone you expect to get an object of both the same state (fields), and the same class (overridden and added methods). If it returned an object whose internal class designation was Object, you'd only have access to things that Object offers, such as toString(), and you would not be able to access its private fields from another B object, or to assign it to a B type variable.

RealSkeptic
  • 33,993
  • 7
  • 53
  • 79
  • Object.clone does a shallow copy, not a deep copy – lbalazscs Dec 01 '14 at 10:09
  • @Ibalazscs true, but the implementations of it within user's classes usually have to do the deep copying themselves. That's why they usually need to override it and don't just keep it as is. – RealSkeptic Dec 01 '14 at 10:10
  • @ReakSkeptic not sure what is meant by "access private fields from another B object" in last line of your answer. Private fields cannot be negotiated using cloning, subclassing, etc. – Prabhat Gaur Aug 05 '20 at 13:17
  • @PrabhatGaur If you are within the source code of class `B` and you get a `B` type object and clone it, you'd be able to access all its private fields. – RealSkeptic Aug 05 '20 at 15:40
  • @RealSkeptic "if you are within the source code of class B" you dont require clone to access private fields of such an object – Prabhat Gaur Aug 10 '20 at 07:11
  • @PrabhatGaur I think you are misunderstanding something. Suppose you have a method in your class, in which you first create a clone of an object of the same class (`this` or something that was passed to that method), and then make changes in the clone and return it. You can access the private fields in that method. You wouldn't be able to if the clone was not of the correct class. – RealSkeptic Aug 10 '20 at 10:25
6

Look at the clone documentation:

Otherwise, this method creates a new instance of the class of this object and initializes all its fields with exactly the contents of the corresponding fields of this object, as if by assignment; the contents of the fields are not themselves cloned.

This operation can be done very efficiently with native code, as some memory has to be copied directly. It is similar in that regard to System.arrayсopy, which is also native. For details see this question: Is it possible to find the source for a Java native method?

Note that usually you should avoid Object.clone(), and use for example a copy constructor instead, see How do I copy an object in Java?

Community
  • 1
  • 1
lbalazscs
  • 17,474
  • 7
  • 42
  • 50
0

It is native, because some system classes' Clone() method are written in C++ to improve performance.

RandomSeed
  • 29,301
  • 6
  • 52
  • 87
Adem
  • 9,402
  • 9
  • 43
  • 58
  • How does this answer the question? – Maroun Dec 01 '14 at 08:49
  • it is the reason that is thrown exception – Adem Dec 01 '14 at 08:50
  • Read the question again. – Maroun Dec 01 '14 at 08:50
  • ok. I think I should read all the changing question and I should change my answer according to current question. btw, it was the answer for original question – Adem Dec 01 '14 at 08:51
  • The question has not significantly changed except for formatting. This was not an answer to the question asked at any point. – Chris Hayes Dec 01 '14 at 08:52
  • ok, I changed my answer. it is answer for current version. I hope it will not change again – Adem Dec 01 '14 at 08:56
  • @Adem: You still don't get it. Your answer *still* does not answer the question, and it *never* answered the question. From the [initial edit](http://stackoverflow.com/revisions/27224577/1), the question was always about the `Object.clone()`. The user cannot implement `Cloneable` in `Object` as per your suggestion, since it is a system class, and you can't change it. – Amadan Dec 01 '14 at 09:21
  • 2
    There has been some confusion here. The original question was poorly phrased (and still is), and this answer, in its first versions, was actually besides the point. I believe this is not the case anymore. Indeed, this answer is far from excellent, but please stop the bashing. – RandomSeed Dec 01 '14 at 09:27
0

clone() is native because the operation depends on the underlying platform, aka OS. Here are some facts to help grasp what is actually happening: 1. The JVM is implemented in C++ 2. C++ requires you to compile the code on the target platform/OS 3. The clone() operation takes place in memory 4. That part of the memory is controlled by the JVM (a C++ program) 5. A class is compiled to bytecode = text(ignore all the lengthy details below, they are just for illustration) So, this:

public static void main(String[] args) {
    int a = 1;
    int b = 2;
    int c = calc(a, b);
}
static int calc(int a, int b) {
    return (int) Math.sqrt(Math.pow(a, 2) + Math.pow(b, 2));
}

becomes this:

public static void main(java.lang.String[]);
  descriptor: ([Ljava/lang/String;)V
  flags: (0x0009) ACC_PUBLIC, ACC_STATIC
  Code:
    stack=2, locals=4, args_size=1
       0: iconst_1
       1: istore_1
       2: iconst_2
       3: istore_2
       4: iload_1
       5: iload_2
       6: invokestatic  #2         // Method calc:(II)I
       9: istore_3
      10: return
static int calc(int, int);
  descriptor: (II)I
  flags: (0x0008) ACC_STATIC
  Code:
    stack=6, locals=2, args_size=2
       0: iload_0
       1: i2d
       2: ldc2_w        #3         // double 2.0d
       5: invokestatic  #5         // Method java/lang/Math.pow:(DD)D
       8: iload_1
       9: i2d
      10: ldc2_w        #3         // double 2.0d
      13: invokestatic  #5         // Method java/lang/Math.pow:(DD)D
      16: dadd
      17: invokestatic  #6         // Method java/lang/Math.sqrt:(D)D
      20: d2i
      21: ireturn
  1. Class methods are shared => NOT cloned; they identified internally with pointers (a method is nothing more than a grouping of instructions, so to point to that grouping you only need to point to the first instruction of the grouping)
  2. An object is then just a specific state of instance variables
  3. To clone an object, the method clone() only needs to copy the instance variables within memory. And it appears it does this as chunk of bytes - there is no analysis taking place as with calling the constructor new SomeClassname() - figure out where the class is in memory, where constructor is, then figure out the variable types, pass the initialization values, if any, and perform assignments, if any. You get the picture.
  4. Since clone() is called on a specific object of a given type, the type itself is already known and the analysis in (8) above is not needed. Even the values of the instance variables are the same, so we do not need to pass anything.
  5. The only issue remaining is with DEEP copies - handling the references to dependencies by calling clone() on each dependency object and assigning the reference to the instance variable in the wrapper clone.

I know this was lengthy, but it illustrates quite clearly why clone() is faster than "new" - just grabs the state of the object as binary string and copies it without any "thought"/checks.

To learn more about bytecode, take a look at this article in DZone. And remember .... EVERYTHING in Computer Science is FAKE, including classes objects because they are just another abstraction that puts together related structs and functions, except probably for the hardware :), which most people think actually belongs in Computer Engineering, and not in CS.

George Smith
  • 438
  • 4
  • 8