239

I was told by a colleague that in Java object creation is the most expensive operation you could perform. So I can only conclude to create as few objects as possible.

This seems somewhat to defeat the purpose of object oriented programming. If we aren't creating objects then we are just writing one long class C style, for optimization?

We're looking for long answers that provide some explanation and context. Don't just give a one-line answer; explain why your answer is right, ideally with citations. Answers that don't include explanations may be removed.

  • 39
    "Java object creation is the most expensive operation you could perform". Mind sharing the source of that claim? – Songo May 22 '12 at 9:23
  • 92
    And - most expensive operation as compared to what? Compared to calculating pi to 900 digits or compared to incrementing an int? – jasonk May 22 '12 at 9:55
  • 4
    Might they have been talking about a particular part of that specific object creation? I'm thinking how Apple uses a queue for tableViewCells. Perhaps your colleague was suggesting to create a few objects and reuse them due to some overhead associated with those specific objects? Just trying to figure out why they'd make such a claim. – Tyler DeWitt May 22 '12 at 17:21
  • 3
    This is one of the most funny things I've ever heard about programming .) – Mert Akcakaya May 24 '12 at 8:58
  • 22
    Arithmatic is quite expensive too; we should avoid calculations, oh, and starting a JVM is really expensive so we should not start any JVMs :-). – James Anderson Aug 2 '13 at 1:24

14 Answers 14

470
+50

Your colleague has no idea what they are talking about.

Your most expensive operation would be listening to them. They wasted your time mis-directing you to information that is over a decade out of date (as of the original date this answer was posted) as well as you having to spend time posting here and researching the Internet for the truth.

Hopefully they are just ignorantly regurgitating something they heard or read from more than a decade ago and don't know any better. I would take anything else they say as suspect as well, this should be a well known fallacy by anyone that keeps up to date either way.

Everything is an Object ( except primitives )

Everything other than primitives ( int, long, double, etc ) are Objects in Java. There is no way to avoid Object creation in Java.

Object creation in Java due to its memory allocation strategies is faster than C++ in most cases and for all practical purposes compared to everything else in the JVM can be considered "free".

Early as in late 1990's early 2000s JVM implementations did have some performance overhead in the actual allocation of Objects. This hasn't been the case since at least 2005.

If you tune -Xms to support all the memory you need for your application to run correctly, the GC may never have to run and sweep most of the garbage in the modern GC implementations, short lived programs may never GC at all.

It doesn't try and maximize free space, which is a red herring anyway, it maximizes performance of the runtime. If that means the JVM Heap is almost 100% allocated all the time, so be it. Free JVM heap memory doesn't give you anything just sitting there anyway.

There is a misconception that the GC will free memory back to the rest of the system in a useful way, this is completely false!

The JVM heap doesn't grow and shrink so that the rest of the system is positively affected by free memory in the JVM Heap. -Xms allocates ALL of what is specified at startup and its heuristic is to never really release any of that memory back to the OS to be shared with any other OS processes until that instance of the JVM quits completely. -Xms=1GB -Xmx=1GB allocates 1GB of RAM regardless of how many objects are actually created at any given time. There are some settings that allow for percentages of the heap memory to be release, but for all practical purposes the JVM never is able to release enough of this memory for this to ever happen so no other processes can reclaim this memory, so the rest of the system doesn't benefit from the JVM Heap being free either. An RFE for this was "accepted" 29-NOV-2006, but nothing has ever been done about it. This is behavior is not considered a concern by anyone of authority.

There is a misconception that creating many small short lived objects causes the JVM to pause for long periods of time, this is now false as well

Current GC algorithms are actually optimized for creating many many small objects that are short lived, that is basically the 99% heuristic for Java objects in every program. Attempts at Object Pooling will actually make the JVM perform worse in most cases.

The only Objects that need pooling today are Objects that refer to finite resources that are external to the JVM; Sockets, Files, Database Connections, etc and can be reused. Regular objects can not be pooled in the same sense as in languages that allow you direct access to memory locations. Object caching is a different concept and may or may not be what some people naively call pooling, the two concepts are not the same thing and should not be conflated.

The modern GC algorithms don't have this problem because they don't deallocate on a schedule, they deallocate when free memory is needed in a certain generation. If the heap is big enough, then no deallocations happen long enough to cause any pauses.

Object Oriented Dynamic languages are beating C even now days on compute sensitive tests.

  • 270
    +1: "Your most expensive operation would be listening to them ...". Best I've heard for some time. – rjnilsson May 22 '12 at 8:16
  • 21
    @DeadMG, even with the cumulative GC overhead, Java can be faster than C++ (e.g., due to the heap compaction, minimising cache misses for certain data structures). – SK-logic May 22 '12 at 8:43
  • 13
    @SK-logic: As the GC is non-deterministic, it's extremely difficult at best to actually prove that. As for minimising cache misses, it's hard to do that when every object must be another indirection, wasting cache space and increasing execution time. However, I contend that by simply using an appropriate allocator in C++ like object pool or memory arena, you can easily match or beat the performance of the garbage collector. For example, you can write a memory arena class that will perform faster than _alloca, amortized. – DeadMG May 22 '12 at 8:49
  • 31
    Object creation is cheaper now than it used to be. It's not free though. Anyone who tells you that is lying. And the link about OO languages beating C is a exaggerated response to someone who is genuinely trying to learn. – jasonk May 22 '12 at 22:08
  • 16
    It's because of these kind of answers that we end up with crappy code. The right answer is creating an object in Java is both creating the Java object and initializing it. First part is cheap, second can be very expensive. People should always look at what happens in constructors before using the new keyword in a hotspot place. I've seen people use new ImageIcon(Image) in the paint() method of Swing objects, which is pretty expensive and was making the entire UI super sluggish. So it's not a black and white answer, think before you use new somewhere. – qwertzguy Jun 23 '16 at 18:25
92

Bottom line: Don't compromise your design in order to take shortcuts creating objects. Do avoid creating objects unnecessarily. If sensible, design to avoid redundant operations (of any sort).

Contrary to most answers - yes, object allocation DOES have a cost associated. It is a low cost, but you should avoid creating unnecessary objects. Same as you should avoid unnecessary anything in your code. Large object graphs make GC slower, imply longer execution times in that you are probably going to have more method calls, trigger more CPU cache misses, and increase likelihood of your process being swapped to disk in low RAM cases.

Before anyone rants about this being an edge case - I have profiled applications that, before optimising, created 20+MB of objects in order to process ~50 rows of data. This is fine in testing, until you scale up to a hundred requests a minute and suddenly you are creating 2GB of data per minute. If you want to do 20 reqs/sec you are creating 400MB of objects and then throwing it away. 20 reqs/sec is tiny for a decent server.

  • 7
    I may add an example: In some cases it really makes no difference in terms of clarity of code but can make a more or less big difference in performance: When reading from streams, for instance, it is not uncommon to use something like while(something) { byte[] buffer = new byte[10240]; ... readIntoBuffer(buffer); ... which may be wasteful compared to e.g. byte[] buffer = new byte[10240]; while(something) { ... readIntoBuffer(buffer); .... – JimmyB May 22 '12 at 9:41
  • 4
    +1: Unnecessary object creation (or rather cleaning up after removal) can definitely sometimes be costly. 3D Graphics/OpenGL code in java is one place where I have seen optimizations done to minimize the number of objects created since GC can otherwise wreak havoc with your framerate. – Leo May 22 '12 at 14:10
  • 1
    Wow! 20+ MB to process 50 rows of data? Sounds crazy. In any case, are those objects long-lived? Because that's the case that would matter for GC. If on the other hand you're merely discussing memory requirements, that's unrelated to garbage collection or object creation efficiency... – Andres F. May 22 '12 at 23:52
  • 1
    Objects are short-lived (less than 0.5sec in the general case). That volume of garbage still affects performance. – jasonk May 23 '12 at 23:17
  • 2
    Thank you for actually standing firm on reality, anyone who lives with the effects of a thoughtless architecture can very much relate. – J. M. Becker Jun 19 '16 at 20:35
60

Actually, due to the memory management strategies that the Java language (or any other managed language) makes possible, object creation is little more than incrementing a pointer in a block of memory called the young generation. It's much faster than C, where a search for free memory has to be done.

The other part of the cost is object destruction, but it's hard to compare to C. The cost of a collection is based on the amount of objects saved long-term but the frequency of collections is based on amount of objects created... in the end, it's still much faster than C-style memory management.

  • 7
    +1 Even though the garbage collector "just works", every Java programmer should learn about the generational garbage collector. – benzado May 22 '12 at 13:16
  • 18
    The newer versions of Java can do escape analysis, which means that it can allocate memory for objects that don't escape a method on the stack, so that cleaning them up is free - the garbage collector doesn't have to deal with those objects, they're automatically discarded when the method's stack frame is unwound (when the method returns). – Jesper May 22 '12 at 14:28
  • 4
    An the next step for escape analysis is to "allocate" memory for small object purely in registers (for example a Point object could fit in 2 general purpose registers). – Joachim Sauer May 23 '12 at 5:34
  • 6
    @Joachim Sauer: That's kind of what is done in the newer implementations of the HotSpot VM. It's called scalar replacement. – someguy May 24 '12 at 15:02
  • 1
    @someguy: I've read about it some time ago as the next thing, but didn't follow up to check if it's already done. It's excellent news to hear that we already have this. – Joachim Sauer May 24 '12 at 19:31
38

Other posters have rightly pointed out that object creation is extremely fast in Java, and that you should not usually worry about it in any normal Java application.

There are a couple of very special situations where is is a good idea to avoid object creation.

  • When you are writing a latency-sensitive application and wish to avoid GC pauses. The more objects you produce, the more GC happens and the greater the chance of pauses. This might be a valid consideration for relevant for games, some media applications, robotic control, high-frequency trading etc. The solution is to pre-allocate all the objects / arrays you need up front and re-use them. There are libraries that specialise in providing this kind of capability, e.g Javolution. But arguably, if you really care about low latency you should be using C/C++/assembler rather than Java or C# :-)
  • Avoiding boxed primitives (Double, Integer etc.) can be a very beneficial micro-optimisation in certain circumstances. Since unboxed primitives (double, int etc.) avoid the per-object overhead, they are much faster CPU intensive work like numerical processing etc. Typically, primitive arrays perform very well in Java so you want to use these for your number crunching rather than any other kinds of objects.
  • In constrained memory situations you want to minimise the number of (active) objects created since each objects carries a small overhead (typically 8-16 bytes depending on JVM implementation). In such circumstances you should prefer a small number of large objects or arrays to store your data rather than a large number of small objects.
  • 3
    Its worth noting that escape analysis will allow short lived (bounded life) objects to be stored on the stack, these objects can be deallocated for free ibm.com/developerworks/java/library/j-jtp09275/index.html – Richard Tingle Jun 27 '13 at 10:36
  • 1
    @Richard: great point - escape analysis provides some very good optimisations. You have to be careful about relying on it though: it isn't guaranteed to happen in all Java implementations and in all circumstances. So you often need to benchmark to be sure. – mikera Jun 27 '13 at 11:43
  • 2
    Also, 100% correct escape analysis is equivalent to the halting problem. Don't rely on escape analysis in complex situations, as it is likely to give the wrong answer at least some of the time. – Jules Jan 25 '15 at 8:51
  • The first and last points don't apply to small objects that are quickly released, they die in eden (think stack allocation in C, pretty much free) and never effect GC times or memory allocation. Most object allocation in Java falls into this category and is therefore essentially free. The second point is still valid. – Bill K Apr 3 '18 at 16:32
17

There is a kernel of truth in what your colleague is saying. I respectfully suggest the issue with object creation is actually garbage collection. In C++ the programmer can control precisely how memory is deallocated. The program can accumulate crud for as long or as short as it likes. Further, the C++ program can discard the crud using a different thread than the one that created it. Thus the thread currently working never has to stop to clean up.

In contrast, the Java Virtual Machine (JVM) periodically stops your code to reclaim unused memory. Most Java developers never notice this pause, since it is usually infrequent and very short. The more crud you accumulate or the more constrained your JVM is, the more frequent these pauses are. You can use tools like VisualVM to visualize this process.

In recent versions of Java, the garbage collection (GC) algorithm can be tuned. As a general rule, the shorter you want to make the pauses, the more expensive the overhead in the virtual machine (i.e. CPU and memory spent coordinating the GC process).

When might this matter? Any time you care about consistent sub-millisecond response rates, you'll care about GC. Automated trading systems written in Java tune the JVM heavily to minimize pauses. Firms that would otherwise write Java turn to C++ in situations where systems have to be highly responsive all the time.

For the record, I do not condone object avoidance in general! Default to object-oriented programming. Adjust this approach only if the GC gets in your way, and then only after trying to tune the JVM to pause for less time. A good book on Java performance tuning is Java Performance by Charlie Hunt and Binu John.

  • 10
    Most modern JVM's support better garbage collection algorithms than "stop the world". The amortized time spent in garbage collection is frequently less than what is spent explicitly calling malloc/free. Also does C++ memory management run in a separate thread? – user1249 May 22 '12 at 6:59
  • 10
    The newer Java versions from Oracle can do escape analysis, which means that objects that don't escape a method are allocated on the stack, which makes cleaning them up free - they are automatically deallocated when the method returns. – Jesper May 22 '12 at 14:37
  • 2
    @ThorbjørnRavnAndersen: Really? Do you really mean pause-less GC, or do you mean "usually-parallel-but-sometimes-a-tiny-bit-pausing" GC? I don't understand how the GC can never pause a program, and yet move objects around at the same time... it seems, quite literally, impossible to me... – Mehrdad May 23 '12 at 6:56
  • 2
    @ThorbjørnRavnAndersen: How can it "stop the world" but never "pause the JVM"? That makes no sense... – Mehrdad May 23 '12 at 7:52
  • 2
    @ThorbjørnRavnAndersen: No I really don't; I just don't understand what you're saying. Either the GC sometimes pause the program, in which case it is -- by definition -- not "pauseless", or it never pauses the program (hence, it is "pauseless"), in which case I don't understand how that corresponds to your "it stops the world when it cannot keep up" statement, since that would seem to imply that the program is paused while the GC is operating. Would you mind explaining which is the case (is it pauseless or not?), and how that is possible? – Mehrdad May 23 '12 at 8:03
11

There is one case where you may be discouraged from creating too many objects in Java because of the overhead - designing for performance on the Android platform

Other than that, the above answers hold true.

  • 2
    Read the question again. It does not specify JVM anywhere including the tags. It only mentions Java. – Peter Kelly May 22 '12 at 15:08
9

the GC is tuned for many short lived object

that said if you can trivially reduce object allocation you should

one example would be building a string in a loop, the naive way would be

String str = "";
while(someCondition){
    //...
    str+= appendingString;
}

which creates a new String object on each += operation (plus a StringBuilder and the new underlying char array)

you can easily rewrite this into:

StringBuilder strB = new StringBuilder();
while(someCondition){
    //...
    strB.append(appendingString);
}
String str = strB.toString();

this pattern (immutable result and a local mutable intermediate value) can be applied to other things as well

but other than that you should pull up a profiler to find the real bottleneck instead of chasing ghosts

  • the biggest advantage in this StringBuilder approach is the pre-size the StringBuilder so that it never has to reallocate the underlying array with the StringBuilder(int) constructor. This makes it a single allocation, rather than a 1+N allocations. – Jarrod Roberson May 22 '12 at 18:11
  • 2
    @JarrodRoberson StringBuilder will at least double the current capacity or in other words the capacity will grow exponentially for only log(n) allocations – ratchet freak May 22 '12 at 19:09
6

Joshua Bloch (one of Java platform creators) wrote in his book Effective Java in 2001:

Avoiding object creation by maintaining your own object pool is a bad idea unless the objects in the pool are extremely heavyweight. A prototypical example of an object that does justify an object pool is a database connection. The cost of establishing the connection is sufficiently high that it makes sense to reuse these objects. Generally speaking, however, maintaining your own object pools clutters up your code, increases memory footprint, and harms performance. Modern JVM implementations have highly optimized garbage collectors that easily outperform such object pools on lightweight objects.

  • 1
    Even with things like network connection, what's important is not to maintain the GC-allocated objects associated with connections, but rather to maintain the set of connections which exist outside the GC-managed world. There are times when pooling objects themselves can be helpful; most of those stem from cases where a pair of references to the same object may be semantically equivalent to a pair of references to identical-but-distinct objects, but nonetheless have some advantages. For example, two references to the same fifty-thousand-character string may be checked for equality... – supercat Dec 29 '14 at 20:49
  • 2
    ...much faster than references to two distinct-but-identical strings of that length. – supercat Dec 29 '14 at 20:49
5

This really depends on the specific application, so it's really hard to say in general. However, I would be pretty surprised if object creation was actually a performance bottleneck in an application. Even if they are slow, the code-style benefit will probably outweigh the performance (unless it's actually noticeable to the user)

In any case, you shouldn't even start to worry about these things until you have profiled your code to determine the actual performance bottlenecks instead of guessing. Until then, you should do whatever is best for code readability, not performance.

  • In early versions of Java there was a substantial cost incurred when the garbage collector cleaned up discarded objects. Recent versions of Java have greatly enhanced GC options, so object creation is rarely an issue. Usually web systems are limited by IO calls to external systems unless you're computing something truly complex on the application server as part of the page load. – greg May 22 '12 at 2:18
3

I think your colleague must have said from the perspective of unnecessary object creation. I mean if you are creating the same object frequently then it is better to share that object. Even in cases where object creation is complex and takes more memory, you might want to clone that object and avoid creating that complex object creation process(But that depends on your requirement). I think the statement "Object creation is expensive" should be taken in context.

As far as JVM memory requirements are concerned, wait for Java 8, you don't even need to specify -Xmx, meta space settings will take care of JVM memory need and it will grow automatically.

  • It would be very constructive if people put comment also while down voting any answer. After all we are all here to share knowledge, and simply passing judgment without proper reason is not going to serve any purpose. – AKS Aug 2 '13 at 11:33
  • 1
    Stack exchange should have some mechanism to notify users who down vote any answer, when comment is posted on that answer. – AKS Aug 2 '13 at 16:46
1

There's more to creating a class than allocating memory. There's also initialization, I'm not sure why that part is not covered by all the answers. Normal classes contain some variables, and do some form of initialization, and that isn't free. Depending on what the class is, it may read files, or do any other number of slow operations.

So just consider what the class constructor does, before figuring if it's free or not.

  • 2
    A well-designed class shouldn't do heavy-lifting in its constructor, for just this reason. For example, your file-reading class could lower its cost of instantiation by only verifying that its target file exists on startup, and deferring any actual file operations until the first method call that needs data from the file. – GordonM May 24 '12 at 6:00
  • 2
    If the additional cost is moved to the 'if (firstTime)', than recreating class in a loop is still more expensive than reusing the class. – Alex May 24 '12 at 14:19
  • I was about to post a similar answer, and I believe this is the right answer. So many people are blinded by those sayings that creating Java objects is cheap that they don't realize that often constructors or further initialization can be far from cheap. For example the ImageIcon class in Swing, even if you pass it an pre-loaded Image object, the constructor is pretty expensive. And I disagree with @GordonM, many classes from the JDK perform most of the init in the constructor, and I think it makes the code leaner, better designed. – qwertzguy Jun 23 '16 at 18:17
1

Java's GC is actually very optimized in terms of creating lots of objects rapidly in a "burst" fashion. From what I can understand they use a sequential allocator (fastest and simplest O(1) allocator for variable-sized requests) for that kind of "burst cycle" into a memory space they call "Eden space", and only if the objects persist after a GC cycle do they get moved to a place where the GC can collect them one-by-one.

With that said, if your performance needs become critical enough (as in measured with real user-end requirements), then objects do carry an overhead but I wouldn't think of it so much in terms of creation/allocation. It has more to do with locality of reference and the additional size of all objects in Java as required to support concepts like reflection and dynamic dispatch (Float is bigger than float, often something like 4 times larger on 64-bit with its alignment requirements, and an array of Float is not necessarily guaranteed to be stored contiguous from what I understand).

One of the most eye-catching things I ever saw developed in Java that made me consider it a heavyweight contender in my field (VFX) was an interactive, multithreaded standard path tracer (not using irradiance caching or BDPT or MLS or anything else) on the CPU providing real-time previews that converged rather quickly to a noise-free image. I've worked with professionals in C++ dedicating their careers to such things with fancy profilers in hand who had difficulty doing that.

But I peered around at the source code and while it used plenty of objects at trivial cost, the most critical parts of the path tracer (the BVH and triangles and materials) very clearly and deliberately avoided objects in favor of big arrays of primitive types (mostly float[] and int[]), which made it use far less memory and guaranteed spatial locality to get from one float in the array to the next. I don't think it's too speculative to think that, if the author used boxed types liked Float there, it would have come at a rather large cost to its performance. But we're talking the most absolutely critical part of that engine, and I'm pretty sure, given how skillfully the developer optimized it, that he measured that and applied that optimization very, very judiciously, since he happily used objects everywhere else with trivial cost to his impressive realtime path tracer.

I was told by a colleague that in Java object creation is the most expensive operation you could perform. So I can only conclude to create as few objects as possible.

Even in a field as performance-critical as mine, you're not going to write efficient products if you hamstring yourself in places that don't matter. I would even make the claim that the most performance-critical fields might put an even higher demand for productivity, since we need all the extra time we can get to tune those hotspots that really matter by not wasting such time on things that don't. As with the path tracer example from above, the author skillfully and judiciously applied such optimizations only to the places that truly, truly mattered, and probably in hindsight after measuring, and still happily used objects everywhere else.

  • 1
    Your first paragraph is on the right track. The eden and young spaces are use copy collectors that have approx. 0 cost for dead objects. I highly recommend this presentation. On a side note, you realize this question is from 2012, right? – JimmyJames Dec 20 '18 at 22:52
  • @JimmyJames I get bored and like to just sift through the questions, including old ones. I hope people don't mind my necromancy! :-D – Dragon Energy Dec 20 '18 at 22:54
  • @JimmyJames Is it no longer the case that boxed types have additional memory requirements and not guaranteed to be contiguous in an array? I tend to think objects are dirt cheap in Java but the one case where they might be relatively expensive is like float[] vs. Float[], where processing a million of the former sequentially might be relatively quite faster than the second. – Dragon Energy Dec 20 '18 at 22:59
  • 1
    When I first started posting here I did likewise. Just don't be surprised when answers to old questions tend to get very little attention. – JimmyJames Dec 21 '18 at 14:46
  • 1
    I'm pretty sure that boxed types should be assumed to use more space than primitives. There are potentially optimizations around that but I in general, I think it is as you describe. Gil Tene (of the presentation above) has another talk about a proposal to add a special kind of collection that would provide some of the benefits of structs but still using objects. It's an interesting idea, I'm not sure of the status of the JSR. The cost is largely due to time which is what you allude to. If you can avoid letting your objects 'escape', they can even be stack allocated and never touch the heap. – JimmyJames Dec 21 '18 at 14:53
0

As people have said object creation is not a big cost in Java (but I bet bigger than most simple operations like adding, etc) and you shouldn't avoid it too much.

That said it still a cost, and sometimes you may find yourself trying to scrap as many object as possible. But only after profiling has shown that this is a problem.

Here is a great presentation on the topic: https://www.cs.virginia.edu/kim/publicity/pldi09tutorials/memory-efficient-java-tutorial.pdf

0

I did a quick microbenchmark regarding this and I have provided full sources in github. My conclusion is that whether creating objects is expensive or not is not the issue, but continuously creating objects with the notion that the GC will take care of things for you will make your application trigger the GC process sooner. GC is a very expensive process and it is best to avoid it whenever possible and not try to push it to kick in.

  • this doesn't seem to offer anything substantial over points made and explained in prior 15 answers. Hardly a content worth bumping a question that was asked over 2 years ago and has gotten a very thorough answer – gnat Jan 25 '15 at 20:27

protected by yannis Aug 2 '13 at 5:39

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.