20

I have been trying to understand the difference between using new to instantiate an object vs using Class.forName("A").newInstance();.

I have run the following code for a simple class A which shows using Class.forname("A").newInstance() is 70-100 times slower than using just new A().

I am curious to know why there is such a difference in time, but couldn't figure out. Please someone help me to understand the reason.

public class Main4test {

    public Main4test() {
    }

    static int turns = 9999999;

    public static void main(String[] args) {
        new Main4test().run();
    }

    public void run() {
        System.out.println("method1: " + method1() + "");
        System.out.println("method2:" + method2() + "");
    }

    public long method2() {
        long t = System.currentTimeMillis();
        for (int i = 0; i < turns; i++) {
            try {
                A a = (A) Class.forName("A").newInstance();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
        return System.currentTimeMillis() - t;
    }

    public long method1() {
        long t = System.currentTimeMillis();
        for (int i = 0; i < turns; i++) {
            try {
                A a = new A();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return System.currentTimeMillis() - t;
    }

}

public class A {
    int a;
    public A() {
    a=0;
    }
}
djv
  • 15,168
  • 7
  • 48
  • 72
karimvai
  • 319
  • 3
  • 14
  • 2
    My guess is that it's looking up a class by name is an expensive operation. The compiler knows nothing about the class so it can't do any optimization. – Ted Hopp Sep 22 '14 at 05:55
  • Also you might need to do something with the instance to ensure the compiler doesn't optimise it away. – sje397 Sep 22 '14 at 05:55
  • 1
    It is reflection and it allows to make new instance of class by name. It is also slower. It loads class and initialize it's static part, so it is used for loading drivers due to side effects. – Ivan Ivanov Sep 22 '14 at 05:56
  • Accomplishing a task via reflection will almost always be slower than doing it directly. With `new A()`, you have one constructor call. With `Class.forName("A").newInstance()`, you have two method calls, both of which probably involve complex inspection of the structure of your binaries, on top of that constructor call. It's simply a more roundabout way of doing it. – ApproachingDarknessFish Sep 22 '14 at 05:57
  • Propably `method1` will even faster with no try-catch-block, that is not neccesary at all. – PeterMmm Sep 22 '14 at 05:57
  • Parts of your question suggest you're concerned with just the speed difference between these, while other parts suggest you want to know about all of the differences. Can you clarify which is the case? – Chris Hayes Sep 22 '14 at 06:04
  • I have been doing study on performance of accomplishing something in various ways in java. My first study goal is in depth analysis of speed issues of various java features and architecture of the features @Chris Hayes. Thanks. – karimvai Sep 22 '14 at 06:29
  • The main difference might come from the fact that for `method1` it’s easier for the hotspot optimizer to prove that it has no side-effects and therefore can be replaced by no-ops. – Holger Sep 22 '14 at 09:21
  • The first time `A` is referenced it need to be loaded - in this case by your first method. Try swapping them around. You need to run your tests without timing first a few thousand times to "warm the JIT". This benchmark tells you nothing... – Boris the Spider Sep 22 '14 at 17:49
  • possible duplicate of [Java Reflection: Why is it so slow?](http://stackoverflow.com/questions/1392351/java-reflection-why-is-it-so-slow) – Raedwald Sep 23 '14 at 06:59

5 Answers5

25
A a = new A();

Calls the new operator and the constructor of A directly, where A is mentioned in the source text and has therefore already been loaded and initialized.

A a = (A) Class.forName("A").newInstance();
  • look to see if A has already been loaded
  • load it if necessary
  • initialize it if necessary
  • locate the no-args constructor via reflection
  • call the new operator and the no-args constructor via reflection
  • typecast the result to A
Alberto
  • 15,626
  • 9
  • 43
  • 56
user207421
  • 305,947
  • 44
  • 307
  • 483
  • Thanks :) I got answer focused to the point and good understanding in short literature. – karimvai Sep 22 '14 at 06:44
  • 8
    Actually you can’t assume that when executing `new A()` the class `A` has already been loaded and initialized. Instead, that might exactly be the point at which `A` is loaded and initialized when it is the first time, `A` is used. Typical JVMs (including Oracle’s JVM) are lazy when it comes to class loading. – Holger Sep 22 '14 at 09:18
  • I'm not an expert in Java workings, however the first step you list (which is probably what takes the bunch of time, since all the others may happend with `new A()` as well as noted by Holger) *could* be optimized away since `Class.forName("A")` is a constant expression, and the compiler *could* produce code very similar to the one produced by `new A()`. Obviously this optimization cannot work with `Class.forName(aGenericExpressionReturningAString)`. Not surprised that the string literal case isn't optimized since, AFAIK, there's really no reason for that idiom. – Bakuriu Sep 22 '14 at 09:55
  • 1
    @Bakuriu It isn't a constant expression unless the compiler can somehow know that it always produces the same result, which it can't, as it needn't. – user207421 Sep 22 '14 at 10:18
  • 1
    @EJP Then how can the compiler avoid the class lookup in `new A()`? If the class associated with `A` can change at runtime the compiler has to look it up every time, even using the other syntax. If the class doesn't change, then the compiler *can* optimize away `Class.forName("A")` with just `A` (I mean, a reference to the class object, thus avoiding lookup by name). – Bakuriu Sep 22 '14 at 10:34
  • 2
    This [small piece of code](http://ideone.com/S0jKZX) demonstrate what Holger says: the class can be loaded on-demand. – nhahtdh Sep 22 '14 at 14:08
  • 1
    @Bakuriu: just because the same code is called does not mean that the compiler knows that calling `Class.forName("A")` a/ produces the same result and b/ does not change something else in the process. `new A` is identified by the compiler as a constructor for a given class, because of the `new` keyword. `Class.forName("A")` is any call to a static method, on which the compiler has no prior knowledge. – njzk2 Sep 22 '14 at 16:26
  • 1
    @Bakuriu: for all the compiler knows, `Class.forName` could be incrementing a counter and returning a random class. – njzk2 Sep 22 '14 at 16:28
  • @njzk2 I fail to see how this is relevant. I'm saying that it wouldn't be a problem to *add an optimization to the compiler*, which *implies* that you *insert* that knowledge into it. There are many similar optimizations used by compilers, and even other kind of checks (e.g. checking string-formatting argument types of the C's `printf`, which is done by most compilers). – Bakuriu Sep 22 '14 at 18:52
  • 1
    @Bakuriu: I don't understand what you mean by `I'm saying that it wouldn't be a problem to add an optimization to the compiler`. At compile time, the compiler does not know the implementation of the `Class.forName` method that will be used at Runtime, and therefore the compiler could never infer on the behavior of that method. – njzk2 Sep 22 '14 at 20:07
  • @njzk2 I'm saying you can just hardcode knowledge about properties of `Class` in the compiler. `Class` requires some compiler help anyway to implement reflection, so you can just implement it *inside* the compiler itself and you are done. – Bakuriu Sep 22 '14 at 20:34
  • 1
    @Bakuriu: That is not really how java works. the bytecode compiled by the compiler does not rely on assumptions regarding the implementation of the target it will run on. Reflection does not rely on the compiler either, it is all runtime. – njzk2 Sep 22 '14 at 20:41
  • @Bakuriu The result of `Class.forName("string")` is not a compile-time constant. (For that matter, neither is the result of mentioning `A` directly in the text, as in `new A().`) Ergo no compiler optimization is possible. – user207421 Sep 23 '14 at 00:05
5

Using reflection Class.forName("A").newInstance(); is not only a costly operation (because the correct class-loader needs to be delegated to and load the class during runtime), but also makes your code more difficult to debug and you lose all the advantage of type safety (which takes place during compilation).

Conclusion:
Avoid reflection unless you must use it (for example if you're writing aspect-oriented plugin/library)

Nir Alfasi
  • 53,191
  • 11
  • 86
  • 129
4

The difference between new operator and newInstance method is listed below:

  • new operator can be used with any constructor of the class by passing any number of arguments as accepted by the constructor. newInstance method requires the presence of no-arg constructor in the class for which it has been invoked. If you want to use a constructor with newInstance, then you need to get an instance of Constructor class for any constructor and then invoke newInstance like:

    Class class = Class.forName("A");  
    Constructor const = class.getConstructor(A.class);  
    A a = null;  
    const.newInstance(a);
  • Using new operator doesn’t require explicit class loading as it is internally handled by the JVM. For newInstance() method an instance of that class’s Class object is required (Class.forName(“A”).newInstance(); or as shown in above point). The Class object referring to the underlying class is obtained by invoking the forName method.

  • The use of new operator is recommended when the name of class is known at compile time. Since newInstance uses reflection to create an object of class, it is recommended to be used when the class is not known at compile time but is determined at run time.

  • Since there is no extra processing related to method invocation like forName in new operator, it is faster than newInstance. The use of newInstance results in extra processing on part of JVM (type checks, security checks) and hence is not recommended to be used for performance degradation reasons.(at least when thousands of instances are being created using newInstance)

  • All Java developers are supposed to know the new operator as it is basic concept which is taught at beginner level, so there is nothing special to learn about it. Not all developers working on a application be aware of reflection and hence there is a learning curve for beginners working on the code with newInstance method.

  • You can see new operator being used in any normal Java program. newInstance is being used at multiple places inside Java especially in server side like loading and instantiating servlets, applets, JNDI stub/skeletons, JDBC database drivers.

  • With new operator, the class loading and object creation is done by the default class loader of JDK.But with newInstance method, one can explicitly specify the class loader to be used for loading class and object instantiation.

  • There are very less chances for runtime exception with new operator. Only rare case is when the class was present during compile time but was not available on classpath during runtime. The use of newInstance method with Class.forName(String …) can result in runtime exception even if the class name passed as argument to forName method is invalid.

  • The use of new operator results in generation of corresponding byte code in the .class file. When newInstance is used, there is no extra byte code generated for object creation inside the class as object creation is handled dynamically.

  • With new operator there is inherent type checking and compiler error is shown if the class doesn’t exist. Since the class name is passed as argument to Class.forName method as string, there is no compile type checking and usually results in run time exception as described in one of the earlier points.

Ref: http://www.javaexperience.com/difference-between-new-operator-and-class-forname-newinstance/

Vipul Paralikar
  • 1,508
  • 10
  • 22
2

The primary difference between the conventional new and newInstance is that newInstance allows the flexibility to instantiate a class that you don't know until runtime, and makes your code more dynamic. When the class is not known until runtime, then it is a valid case where you should use reflection.

From the Javadoc, the invocation Class.forName(String) returns the Class object associated with the class or interface with the given string name i.e. it returns the Class A

So A a = (A) Class.forName(“A”).newInstance() breaks down to:

  • Class.forName(“A”)
    returns the Class A of type Class.

  • Class.forName(“A”).newInstance() Creates a new instance of the class represented by this Class object, so you get an instance of type A. The class is instantiated as if by a new expression with an empty argument list. The class is initialized if it has not already been initialized. This is here actually equivalent to a new A() and which returns a new instance of A.

    Important: Use of this method effectively bypasses the compile-time exception checking that would otherwise be performed by the compiler.

Reference:

Community
  • 1
  • 1
Infinite Recursion
  • 6,511
  • 28
  • 39
  • 51
-2

the test you use to measure speed is not a valid test. Java performance is very complex and it involves hotspot vm, smart compilers and garbage collectors to start with.

In method 1 java wil be usually smart enough to only make 1 instance of A in memory and reuse it for each iteration

in method 2 you are forcing the VM to use reflection and classloaders to make the Object. that in itself is already slower

Peter
  • 5,728
  • 20
  • 23
  • 1
    This is simply wrong. Java will create a new instance even in `method1()`. – Uwe Plonus Sep 22 '14 at 06:52
  • 1
    maybe i wasent clear, offcourse it will make a new instance but the VM will not have to allocate new memory for it. It is smart enoguh to reuse the previous allocation – Peter Sep 22 '14 at 06:55
  • 3
    even then Java will not reuse the memory as this is work to be done by the GC. The GC logic is complex enough in itself witout such "optimizations". – Uwe Plonus Sep 22 '14 at 07:08
  • Java is just as likely to reuse the same memory in both cases. It reaches a certain point where it needs *N* bytes and either they are there in the same place as last time or they aren't. This is not a difference between the two cases. – user207421 May 19 '16 at 05:35