276

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?

cjapes
  • 5
Slamice
  • 2,657

14 Answers14

519

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 1990s 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" 2006-11-29, 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.

Nayuki
  • 179
108

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.

Vatine
  • 4,269
jasonk
  • 1,703
62

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.

amara
  • 1,378
40

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.
mikera
  • 20,777
18

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.

greg
  • 535
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.

10

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

ratchet freak
  • 25,986
9

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.

6

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.

Oleksi
  • 11,964
4

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.

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.

AKS
  • 383
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.

Alex
  • 137
1

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.

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

rkj
  • 125